4

我有一个大问题,因为我不明白指针在 delphi 中是如何工作的

首先,我从 dll 中获取函数声明。

功能:

type
  TMICRCallback   = function: Integer; stdcall;

然后我在我的代码中声明一个函数。

function CBMICRRead : Integer;stdcall;

该功能非常简单(这是一个示例)

function TCustomizedTenderPlugin.CBMICRRead : Integer; stdcall;
var
  SUCCESS:integer;
begin
   SUCCESS:=1;
   Result:= SUCCESS;
end;

我声明一个这样的变量

Respuesta : TMICRCallback;

当我尝试将此变量分配给我的函数时,问题发生了:(

Respuesta      := CBMICRRead;

这是我第一次在 delphi 中使用指针,所以这可能是一个愚蠢的问题,但请帮助我

4

3 回答 3

6

TCustomizedTenderPlugin.CBMICRRead是一个实例方法。这意味着为了调用它,您必须有一个实例来调用它。

另一方面,TMICRCallback函数指针。它与普通函数而不是实例方法兼容。

它们根本不兼容。为了与您TCustomizedTenderPlugin.CBMICRRead兼容,TMICRCallback您需要将其定义为:

TMICRCallback = function: Integer of object; stdcall;

of object表示此类型与实例方法兼容。类型变量TMICRCallback(如本答案中所定义)同时包含函数指针和实例指针。它有时被称为双指针函数类型。

在继续之前,我建议您仔细阅读文档


我注意到您正在stdcall为这些函数指针使用调用约定。这通常表明您正在尝试与外部模块进行互操作。这不是实例方法可靠的东西。我的意思是你不能用of objectDelphi 以外的语言实现实例方法。如果此代码注定要在互操作设置中使用,那么您应该避免使用of object.

对于互操作设置,您通常会将实例指针作为单独的参数包含在内。在这种情况下,Delphi 声明将如下所示:

type
  TMICRCallback = function(Data: Pointer): Integer; stdcall;

然后,您将实现这样的功能

type
  TPlugin = class
    function CBMICRRead: Integer;
  end;

.....

function PluginCBMICRReadCallback(Data: Instance): Integer; stdcall;
begin
  Result := TPlugin(Data).CBMICRRead;
end;

function TPlugin.CBMICRRead: Integer;
begin
  Result := ....
end;

最后,需要传递回调的外部模块中的函数PluginCBMICRReadCallback和实例的实例指针TPlugin。也许有点像这样:

procedure RegisterCallback(Callback: TMICRCallback; Data: Pointer); stdcall;

你会这样称呼它:

var
  Plugin: TPlugin;
....
Plugin := ...;//get this instance from somewhere
RegisterCallback(PluginCBMICRReadCallback, Plugin);

相关问题中查看了 C++ 代码后,界面的 C++ 端似乎如下所示:

int WINAPI BiMICRSetReadBackFunction(int    nHandle, 
                                     int    (CALLBACK *pMicrCB)(void),
                                     LPBYTE pReadBuffSize,   
                                     LPBYTE readCharBuff,    
                                     LPBYTE pStatus,         
                                     LPBYTE pDetail); 

这个回调甚至不承认数据指针,所以你根本不能使用实例方法。你是如何为多个实例实现回调的,这超出了我的理解!无论如何,你可以像这样在 Delphi 中声明这个函数:

type
  TMICRCallback = function: Integer; stdcall;

function BiMICRSetReadBackFunction(
  nHandle: Integer;
  MicrCB: TMICRCallback;
  pReadBuffSize: PByte;
  readCharBuff: PByte;
  pStatus: PByte;
  pDetail: PByte
): Integer; stdcall; external dllname;

要调用它,你需要这个:

function MICRCallback: Integer; stdcall;//not the method of a class
begin
  Result := ....
end;
.....
retval := BiMICRSetReadBackFunction(..., MICRCallback, ....);
于 2012-10-09T16:17:16.287 回答
0

显然CBMICRRead被定义为对象方法(即 的方法TCustomizedTenderPlugin),因此不是“独立”函数。正因为如此,你需要做

type
  TMICRCallback   = function: Integer of object; stdcall;
于 2012-10-09T16:13:10.147 回答
0

如果 DLL 中的函数声明不是您编写的对象方法,您可以通过将该函数声明为全局函数而不是对象的方法来解决此问题,或者您可以将其声明为目的。

class function CBMICRRead: Integer; static; stdcall;
于 2012-10-09T16:22:00.607 回答