Delphi:使.dll导出一个通过type关键字声明的方法

时间:2015-07-07 07:39:16

标签: delphi

我有一个用Delphi编写的库L,它使用方法M.程序P使用库L的方法M.

L看起来有点像这样:

library L;

// uses and stuff ...

function M(i: Integer; k: Integer): Integer stdcall;
begin
    Result := i*k;
end;

exports
    M;

begin
end.
P看起来有点像这样:

// uses and begin and class and stuff ...

type
  TTheMethod = function(i: Integer; k: Ineteger): Integer stdcall;

var
    hLib: THandle;
    methodVar: TTheMethod; 
    a: Iteger;
begin
    hLib := LoadLibrary(PWideChar('someFile.dll'));
    methodVar:= GetProcAddress(hLib, 'M');
    a := methodVar(2, 21);

如果我改变我的库以便M期望3个整数,那么程序P仍然会编译。 Delphi并不知道M和methodVar需要具有相同的类型。如果M和methodVar中只有一个更改了类型,我希望我的编译器失败。

我尝试将库更改为:

function _M(i: Integer; k: Integer): Integer stdcall;
begin
    Result := i*k;
end;

var
    M: TTheMethodA = _M;

exports
   M;

但那不会编译。

我可以以某种方式让编译器为我检查类型吗?

2 个答案:

答案 0 :(得分:2)

  

我可以以某种方式让编译器为我检查类型吗?

不,你不能。编译器根本无法验证外部函数的签名。实际上,从DLL导出的函数不包含任何元数据来标识其签名。

你得到的最接近的是C ++名称修改,它在其装饰名称中编码函数的签名。但是,这对你没有用,因为Delphi没有任何名称修改功能。

至于您的代码,您无法导出过程类型的变量。您必须导出实际功能。您可以像这样编写最后一段代码:

 divInput.onkeypress = function (event){
                return someTestFunc();
    }


    divInput.tabIndex="-1";

    $(divInput).focusout(function (e) {
        if ($(this).find(e.relatedTarget).length == 0) {
            addToList();
        }
    });

或者,如果您希望通过变量进行路由的灵活性,那么您将以类似的方式进行:

function _M(i: Integer; k: Integer): Integer stdcall;
begin
  Result := i*k;
end;

function M(i: Integer; k: Integer): Integer stdcall;
begin
  Result := _M(i, k);
end;

exports
   M;

答案 1 :(得分:0)

没有办法做到这一点。 GetProcAddress只提供了一个指向过程条目的指针,而没有任何附加信息应该如何调用它,它需要多少个参数,如何以及在哪个顺序传递参数。即使是C ++名称错误,也无法帮助你,因为毕竟 - 它只是一个错误的名称,没有什么能阻止你向方法传递错误的参数计数(毕竟它的简单指针)。使用它可以达到的最大值 - .... $http({ url: aAPIname, method: "POST", data: req, responseType: "arraybuffer", headers: oHeaders, }) .success(function(data, status) { deff.resolve(data); }) .... 将无法找到更改的过程,因为它的名称会有所不同。但它仍然是运行时检查而不是编译时验证。