我写了一个dll :
  文件名:myRun.dll,包涵一个form
  接口函数:function Execute(AHandle:HWnd;para1:integer):string; export; stdcall;实现如下:
function Execute(AHandle:HWnd ;para1:integer):string;
var
  msg : string;
begin
 Result :='Fault';
 try
  Application.Handle:=THandle(AHandle);
  Application.CreateForm(TdemofrmForm,demofrmForm);
  with demofrmForm do
  begin
    ListBox1.Items.clear;
    ListBox1.Items.Add('Input params:'+#13#10);
    ListBox1.Items.Add('[Handle]:'+vartostr(AHandle));
    ListBox1.Items.Add('[param1]:'+inttostr(para1));
    ShowModal;
    Result :='OK';
  end;
 except
  on E: Exception do
   messagebox(0,pchar(e.Message),'Execute',mb_iconwarning)
 end;
end;
主调用函数定义如下:
function Rundll32(xdll: string; AName: string;
  Params: array of const): DWord;
const
  RecSize = SizeOf(TVarRec); 
var
  PFunc: Pointer;
  ParCount: DWord;
  AHandle :THandle;
begin
  AHandle:=LoadLibrary(pchar(xdll));
  if AHandle=0
  then Exit;
  PFunc := GetProcAddress(AHandle,pchar(AName));
  if not Assigned(PFunc) then
    raise Exception.CreateFmt('找不到 %s 的 Method: %s', [xdll,
      AName]);  ParCount := High(Params) + 1; // 获取参数个数  asm
    PUSH        ESI                 // 保存 ESI,我们待会儿要用到它    MOV         ESI, Params         // ESI 指向参数表首址
    CMP         ParCount, 1         // 判断参数个数
    JB          @NoParam
    JE          @OneParam
    CMP         ParCount, 2
    JE          @TwoParams
    CMP         ParCount, 3
    JE          @Threeparams  @ManyParams: // 超过三个参数
    CLD                             // 清空方向标志
    MOV         ECX, ParCount
    SUB         ECX, 3              // 循环 ParCount - 3次
    MOV         EDX, RecSize        // EDX 依次指向每个参数的首址,每次递增 8 Bytes
    ADD         EDX, RecSize        // 跳过前两个参数
  @ParamLoop:
    MOV         EAX, [ESI][EDX]     // 用基址变址寻址方式取得一个参数
    PUSH        EAX                 // 参数进栈
    ADD         EDX, RecSize        // EDX 指向下一个参数首址
    LOOP        @ParamLoop  @Threeparams: // 三个参数
    MOV         ECX, [ESI] + RecSize +RecSize  @TwoParams: // 两个参数
    MOV         EDX, [ESI] + RecSize  @OneParam: // 一个参数
    MOV         EAX, [ESI]
  @NoParam:
    CALL        PFunc               // 调用方法
    MOV         Result, EAX         // 返回值放入 Result
    POP         ESI                 // 记得还原
  end;  
end;实际调用如下:
procedure TForm1.Button5Click(Sender: TObject);
begin
  RunDll32('c:\myRun.dll','Execute',[Handle,123123]);
end;问题:
1.为什么dll调用总是报告无效句柄.
2.传递的参数总是不正确.
3.返回值无法回写.这是什么问题,各位帮我看看.

解决方案 »

  1.   

    DLL的接口用了String本来就是错误
    只能用PChar的
      

  2.   

    问题很大, 你写的汇编代码问题非常大首先, 你是假设函数的调用协议是 register, 而 Windows 下一般的 API 基本上是 stdcall其次, stdcall, cdecl 压栈顺序是从右到左, register 和 pascal 是从左到右最后, stdcall, cdecl 对结构数据传递总是通过压栈, 按4字节方式压入好好琢磨一下调用协议及参数传递和返回值处理
      

  3.   

    我的string类型只是传送DLL完整地址和接口函数名称啊,这和实际的调用没关系的,
      

  4.   

    CALL        PFunc               // 调用方法
    这句就是调用动态库中函数啊!