首页 新闻 会员 周边

请教Delphi动态调用dll的问题

0
悬赏园豆:20 [已解决问题] 解决于 2014-12-29 10:54

Delphi中动态调用dll的方法如下

 1 function GTPEnviormentState(aa:string): WideString;
 2 const
 3   dllName = 'Test.dll';
 4   funName = 'EnviormentState';
 5 var
 6   dllHandle: THandle;
 7   fullDllName: WideString;
 8   func: function(url: WideString): LPWSTR; stdcall; //每个函数不一样
 9   addr:pchar;
10   
11 begin
12   try
13     fullDllName := TGTPPath.GetToolsWorkSpaceDir + '\' + dllName;
14     dllHandle := LoadLibraryW(PWideChar(fullDllName));
15     try
16       if dllHandle <> 0 then
17       begin
18         @func := GetProcAddress(dllHandle, funName);
19         if Assigned(func) then
20         begin
21          // Result := func(strJson);
22         end
23         else Result := '';
24       end
25       else Result := '';
26     finally
27       FreeLibrary(dllHandle);
28     end;
29   except on E: Exception do
30     begin
31       Result := '';
32 
33     end;
34   end;
35 end;

 

这个函数没有问题,可以正常执行。

但是如果我有很多函数都需要动态调用,就需要把上面的方法复制很多遍。但其实只有很少一部分变动,其他都是固定的 

func: function(url: WideString): LPWSTR; stdcall; //每个函数不一样

有什么办法把这个方法抽象出来?  变的部分当作参数传进去 ?

函数的返回值,参数都有可能不相同。 最好不要污染全局变量, 本人刚刚接触Delphi,非常感谢

卒子的主页 卒子 | 小虾三级 | 园豆:588
提问于:2014-12-26 17:09
< >
分享
最佳答案
0

网上搜到答案了,测试通过。不过我测试了一下静态和动态调用的性能,相差一个数量级左右

代码

function CallFunc(dllname, funcname: string; const param: array of const): DWORD;
var
   hLib: THandle;
   pFunc: Pointer;
   intSize: Integer;
begin
   Result := 0;

   hLib := LoadLibrary(PChar(dllname));
   if hLib <> 0 then
   begin
     pFunc := GetProcAddress(hLib, PChar(funcname));
     if pFunc <> nil then
     begin
       // 获取参数大小
       intSize := Length(param);

       // 以下汇编码将自动完成函数调用
       asm
         push ecx
         push esi

         mov ecx, intSize;   // 参数的个数
         mov esi, param

         test ecx, ecx       // 判断是否有参数
         je @call             // 如果没有参数则跳转到函数调用处

       @again:
         dec ecx             
         push dword ptr [esi + ecx * 8]   // 循环把参数压入堆栈
         cmp ecx, 0          
         jnz @again           // 一直循环到 ecx 为0

       @call:
         call pFunc           // 调用函数
         mov @Result, eax     // 返回值

         pop esi
         pop ecx
       end;
     end;

     FreeLibrary(hLib);
   end;
end; 

 

然后调用的时候如下:

CallFunc('user32.dll', 'MessageBoxA', [0, 'hello world', 'title', MB_OK]);
CallFunc('user32.dll', 'MessageBeep', []);
CallFunc('kernel32.dll', 'Sleep', [1000]);

卒子 | 小虾三级 |园豆:588 | 2014-12-29 10:52
其他回答(2)
0

delphi问题你最好到大富翁论坛上问,这儿大部价屌丝,呵呵。

收获园豆:10
爱编程的大叔 | 园豆:30839 (高人七级) | 2014-12-26 17:18
0

VOID * pFunctionPointer = GetFunctionPointer(funName);

 

@func = (function(url: WideString): LPWSTR; stdcall) pFunctionPointer;

收获园豆:10
Launcher | 园豆:45045 (高人七级) | 2014-12-26 17:48

没有搞明白,请明示,谢谢

支持(0) 反对(0) 卒子 | 园豆:588 (小虾三级) | 2014-12-28 12:30

@卒子: 

function GetFunctionPointer(aa:string): Pointer;

func1: function(url: WideString): LPWSTR; stdcall; //每个函数不一样

func2: function(url: WideString): LPWSTR; stdcall; //每个函数不一样

func1 = GetFunctionPointer("EnviormentState1");

func2 = GetFunctionPointer("EnviormentState2");

支持(0) 反对(0) Launcher | 园豆:45045 (高人七级) | 2014-12-29 09:16
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册