Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi:使.dll导出通过type关键字声明的方法_Delphi - Fatal编程技术网

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

Delphi:使.dll导出通过type关键字声明的方法,delphi,Delphi,我有一个用Delphi编写的库L,它使用方法M。程序p使用库L的方法M 我看起来有点像这样: library L; // uses and stuff ... function M(i: Integer; k: Integer): Integer stdcall; begin Result := i*k; end; exports M; begin end. // uses and begin and class and stuff ... type TTheMe

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

我看起来有点像这样:

library L;

// uses and stuff ...

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

exports
    M;

begin
end.
// 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);
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;
p看起来有点像这样:

library L;

// uses and stuff ...

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

exports
    M;

begin
end.
// 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);
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;
如果我改变我的库,使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;
但这不会编译

我能让编译器帮我检查类型吗

我能让编译器帮我检查类型吗

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

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


对于代码,不能导出过程类型的变量。您必须导出一个实际函数。您可以这样编写最后一段代码:

library L;

// uses and stuff ...

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

exports
    M;

begin
end.
// 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);
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;
或者,如果您希望通过变量实现路由的灵活性,则可以采用类似的方式:

var
  _M: function(i: Integer; k: Integer): Integer stdcall;
  // something must assign to _M at some point!

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

exports
   M;

没有办法做到这一点
GetProcAddress
只提供一个指向过程项的指针,而不提供任何附加信息,即应该如何准确地调用该过程项、需要多少参数、应该如何以及以何种顺序传递参数。就连C++名称Mangle也不会对你有帮助,因为毕竟它只是一个被损坏的名字,没有任何东西阻止你把错误的参数计数传递给方法(毕竟它的简单指针是抛出的)。使用它可以达到的最大值-
GetProcAddress
将无法找到更改的过程,因为它损坏的名称将不同。但它仍然是运行时检查,而不是编译时验证。

我不需要编译器检查生成的目标代码的导出符号的类型签名。我希望它根据源代码和我在其中声明的方法类型检查类型。编译器将检查它可以看到的源代码。编译器可以在编译DLL时检查导出代码。编译器可以在编译EXE时检查导入代码。但是有两个独立的编译步骤,在这两个步骤中,编译器都看不到互操作边界的另一边。编译器可以在两个编译步骤中看到源代码。TTheMethodA类型是在两个comp中可用的源代码中声明的类型。我不需要一种方法来检查编译器生成的符号的类型。我需要一种使用type关键字声明全局方法的方法。我需要一种使用type关键字声明全局方法的方法。你不能那样做<代码>类型用于声明类型。只能导出函数,不能导出过程变量。我的更新向您展示了如何导出一个反过来委托给过程变量的函数。我的更新向您展示了如何导出一个反过来委托给过程变量的函数。好啊但通过这样做,我仍然可以更改库中的类型singnature,并且程序将编译无误。我不需要编译器检查生成的目标代码的导出符号的类型签名。我希望它根据源代码和我在itYes中声明的方法类型检查类型。但编译器无法理解您的dll方法是链接到指针的,您正试图使用
GetProcAddress
方法调用来获取指针。我的解决方法是在一条记录中收集method M的所有参数,并在库和程序中使用该记录类型进行类型检查。当然,编译器无法检查这两条记录是否匹配。您将计数器记录是在两个模块共享的单元中声明的。只要这两个模块都是用相同版本的共享单元编译的,就可以了。最终,对于编译器来说,没有任何故障保护方法可以让您避免任何可以想象的错误。