一个动态调用DLL的 菜鸟问题:假如我在dll中有个函数function Max(X, Y: Integer): Integer; stdcall;然后在主程序中动态调用这个dll,
开始是要myhandle := loadlibrary('*.dll') 
然后就要用GetProcAddress得到函数的地址.
如果将这个地址赋值给一个变量,这个变量的类型是不是必须要 type 成 
TGetMax = function (x:integer;y:integer): integer;stdcall; (就是要跟dll中申明的完全一样)
然后再var  myfunc:TGetMax;
myfun := GetProcAddress(myhandle,'Max');有没有一种通用变量,来保存GetProcAddress返回的值能?我在一些资料上看过 TFarProc类型,可是在delphi帮助中却没有看到,
这个问题甚是迷惑,请各位高手赐教.另外 就是给这个变量赋值问题
有的这么写的:
@myfun := GetProcAddress(DLLHandle, 'Min');
if Assigned(@myfun) then
begin
    D := myfun(2,3);
    showmessage(inttostr(d));
end;还有一种是
myfun := GetProcAddress(DLLHandle, 'Min');
D := myfun(2,3);这两种写法有什么区别,是否都正确?@,Assigned是什么意思?
谢谢先!!

解决方案 »

  1.   

    判断一下你得这个函数在这个dll里面是否找到了,第二种情况容易没有进行这个判断容易出现异常
      

  2.   

    你随便找个dll改一下名替换一下你用的dll,然后使用第二中方法试一下
      

  3.   

    GetProcAddress函数返回的一个地址
    我想如果楼主懂指针的话,上面的问题应该不难理解
      

  4.   

    为第一个问题作了一个方案:{-----------以下是测试用的Project.DLL------------------}
    library Project1;uses
      SysUtils,
      Classes;function Test(V1, V2, V3, V4, V5: integer): integer;stdcall;
    begin
      Result := V1 + V2*V3 - V4 div V5;
    end;exports
      Test;
    {$R *.res}begin
    end.{---------------以下是调用----------------}type
      TArr = array of integer;function RunDllFunc(DllName, FuncName: string; Para: TArr): integer;
    var
      H: THandle;
      F : function:integer;stdcall;{按楼主要求,这样声明的}
      Rst: integer;
    begin
      H := Windows.LoadLibrary(PChar(DllName));
      if H<>0 then begin
        @F := GetProcAddress(H, PChar(FuncName));
      end;
      asm
        mov edi, Para
        mov edx, [edi]-4
      @AGAIN:
        mov eax, [edi]+edx*4-4
        push eax
        dec edx
        cmp edx, 0
        jz @DONE
        jmp @AGAIN
      @DONE:
        call F
        mov Rst, eax
      end;
      Result := Rst;
      FreeLibrary(H);
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      Para : TArr;
      Rst : integer;
    begin
      SetLength(Para, 5);
      Para[0] := 2;
      Para[1] := 4;
      Para[2] := 5;
      Para[3] := 9;
      Para[4] := 3;
      Rst := RunDllFunc('project1.dll', 'Test', Para);
      Showmessage(InttoStr(Rst));{2 + 4*5 - 9/3 = 19}
    end;{只要Para的元素个数与DLL函数的参数个数一致,就可以了。}
      

  5.   

    关于楼主提出的第二个问题,附议三楼,另外我想只要看看下面的代码就明白了:
    type
      TFunc = function (v1,v2: integer): integer;function XX(v1,v2: integer): integer;
    begin
      Result := V1 + V2;
      Showmessage(inttostr(result));
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      P: Pointer;
    begin
      P := @XX;
      TFunc(P)(1,2);
    end;
      

  6.   


    4楼那段汇编码,可以再精简一下:
      asm
        mov edi, Para
        mov edx, [edi]-4
      @AGAIN:
        mov eax, [edi]+edx*4-4
        push eax
        dec edx
        cmp edx, 0
        jnz @AGAIN{比较不为零直接使用jnz跳转循环}
        call F
        mov Rst, eax
      end;
      

  7.   

    GetProcAddress函数返回的一个地址 
    我想如果楼主懂指针的话,上面的问题应该不难理解~~~
      

  8.   

    Assigned就是判断是否为nil
    @myfun表示的是myfun变量的地址
    GetProcAddress按字面意思就可以知道,是指返回过程的地址。(如果找不到,返回nil)
    if Assigned(@myfun) then 也就是if @myfun<>nil then 两者一个意思。
    但是,前者显得"高级"一点,让lz这样初次碰到的时候感觉茫然。
    个人认为,使用第一种比较好,万一,你把dll中改掉了,那么就会出现报地址错误,不好看了。