资源文件中的DLL,在内存中如何调用 小雨哥,还有点问题(100)

  • 主题发起人 主题发起人 hying95
  • 开始时间 开始时间
同样的,那二个辅助函数也需要修改一下:implementation{$R *.dfm}{$R csdll.res}var ShowDemo : function (Number: integer): integer; stdcall = nil;/// 全局的资源DLL模块变量var g_dll_module: Cardinal;/// 1)这个函数把res资源里的dll加载到程序里function LoadDLLFromResource(const ResourceName: AnsiString): Cardinal;var ms: TMemoryStream; rs: TResourceStream;begin ms := TMemoryStream.Create; try rs := TResourceStream.Create(HInstance, ResourceName, 'CDATA'); try ms.CopyFrom(rs, 0); ms.Position := 0; finally rs.Free; end; Result := LoadPE(ms.Memory, ms.Size); finally ms.Free; end;end;/// 2)这个函数把这个dll里的函数取出来function GetAddrFromMemoryDll(dll_module:Cardinal; const Name: AnsiString):Pointer;begin try Result := GetProcAddressPE(dll_module, PAnsiChar(Name)); except Result := nil; end;end;procedure TForm1.Button1Click(Sender: TObject);var Number: integer;begin Number := 0; g_dll_module := LoadDLLFromResource('CSDLL'); if g_dll_module <> 0 then begin @ShowDemo := GetAddrFromMemoryDll(g_dll_module, 'Addtwo'); if @ShowDemo <> nil then Number := ShowDemo(100); end; Caption := IntToStr(Number);end;end.
 
测试用途的 csdll.dpr 如下:library csdll;uses SysUtils, Classes;//{$R *.res}function Addtwo(Number: integer): integer; stdcall;begin Result := Number + 2;end;exports Addtwo;beginend.注意要注释掉Delphi自动生成代码里的 {$R ..} 一句,否则出错。
 
小雨哥,我用的是Delphi7,代码全部用你修改的编译通过,但是一点botton程序直接退出如果在Form1的FormCreate事件中初始化g_dll_module编译通不过procedure TForm1.FormCreate(Sender: TObject);begin g_dll_module := LoadDLLFromResource('CSDLL');end;
 
在OnCreate里放上述代码后,连编译都通不过的话,应该仔细看清楚编译器提供的编译错误信息是什么,按照它要求的进行修正就可以了。点Button后退出,原因比较多,可以使用编译器的调试功能排查故障,通常都是内存访问错误,查清楚是什么导致了内存访问并予以修正就可以了。
 
在OnCreate里放上述代码后access violation at 0x7c94a978: write of address 0x0000030fb4注释OnCreate代码编译通过后点bottonaccess violation at 0x000144a2: read of address 0x0000030fb4
 
这个运行时信息就是你调试的重要提示,你可以顺着这个线索往下找问题。这是一条内存访问违例的提示,按照这个提示,不要去完全屏蔽这条语句,而是要顺着这条语句的走向,去寻找究竟哪个语句发生了访问错误。检查LoadDLLFromResource函数可以发现,可能的内存访问只有二个地方,一个是从内存中获取资源里的DLL,另一个是调用LoadPE函数时,函数内部有一个寻找DLLMain的动作。于是,通常为快速起见,会直接在二个位置的中间打一个断点后运行,看看这二个位置到底是哪个发生了问题。找到问题发生的部位后,根据代码情况,分析可能的故障原因。这就是调试的重要性,建议你可以试试看,如果实在调试不了,再向身边附近的高手请教。
 
你好小雨哥, 你是在D2010下做的,为此我专门下载安装了2010。在2010下没有一点问题。但是退出2010,运行编译的EXE文件,点 button出现“Project1.exe遇到问题需要关闭,我们对此引起的不便表示抱歉。”点关闭后,出现另一对话框"Runtime error 216 at 0000004E"再点确定后得到正确运算结果。不知为何?为何在D7中有问题,搞不清楚,能否请小雨哥,再看看,我用的是D7,而且是汉化了的,自己喜欢delphi自学的,自己是做服装的因此自己周围也是做服装的朋友,我看过小雨哥,为其它朋友的解答,细致有理有据,小雨哥就是高手,我说下在CPU调试窗口按F7单步马上出现内存不能为读或为写。说实话我也不会调试。我晚上再看看,顺便给小雨哥加分,http://www.delphibbs.com/delphibbs/dispq.asp?lid=3986912http://www.delphibbs.com/delphibbs/dispq.asp?lid=3986128上面有两个贴有分,一并给你
 
正巧我电脑上没有安装Delphi7,有时间的话,我会设法装一下测试看看的。你说的情况可能的问题有很多,比如DLL函数导出是否正确、调用方式是否准确等等非技术问题都会导致这个情况。不能利用调试器这个工具,麻烦很大的。
 
请小雨哥(退出Delphi2010后),运行一下你电脑上编译后EXE文件看能否得到运算结果并且没有错误?
 
今天在D7下面和D2010下面一样,在D7上编译后点button可以,没有出错,但是退出D7,运行编译好的EXE文件,点 button出现“Project1.exe遇到问题需要关闭,我们对此引起的不便表示抱歉。”点关闭后,出现另一对话框"Runtime error 202 at 01238c46"再点确定后得到正确运算结果,请小雨哥有时间再看看。给你加分了
 
后退
顶部