"不兼容的类型:方法指针和常规过程"

Raf*_*oto 2 delphi pointers compiler-errors function

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

首先,我从一个DLL中获取一个函数声明.

功能:

type
  TMICRCallback   = function: Integer; stdcall;
Run Code Online (Sandbox Code Playgroud)

然后我在我的代码中声明了一个Function.

function CBMICRRead : Integer;stdcall;
Run Code Online (Sandbox Code Playgroud)

功能真的很简单(这是一个例子)

function TCustomizedTenderPlugin.CBMICRRead : Integer; stdcall;
var
  SUCCESS:integer;
begin
   SUCCESS:=1;
   Result:= SUCCESS;
end;
Run Code Online (Sandbox Code Playgroud)

我宣布像这样的变种

Respuesta : TMICRCallback;
Run Code Online (Sandbox Code Playgroud)

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

Respuesta      := CBMICRRead;
Run Code Online (Sandbox Code Playgroud)

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

Dav*_*nan 6

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

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

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

TMICRCallback = function: Integer of object; stdcall;
Run Code Online (Sandbox Code Playgroud)

of object表明这类型与实例方法兼容.类型的变量TMICRCallback(在本回答中定义)包含函数指针和实例指针.它有时被称为双指针函数类型.

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


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

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

type
  TMICRCallback = function(Data: Pointer): Integer; stdcall;
Run Code Online (Sandbox Code Playgroud)

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

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;
Run Code Online (Sandbox Code Playgroud)

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

procedure RegisterCallback(Callback: TMICRCallback; Data: Pointer); stdcall;
Run Code Online (Sandbox Code Playgroud)

你会这样称呼:

var
  Plugin: TPlugin;
....
Plugin := ...;//get this instance from somewhere
RegisterCallback(PluginCBMICRReadCallback, Plugin);
Run Code Online (Sandbox Code Playgroud)

看了相关问题的C++代码后,界面的C++端看起来像这样:

int WINAPI BiMICRSetReadBackFunction(int    nHandle, 
                                     int    (CALLBACK *pMicrCB)(void),
                                     LPBYTE pReadBuffSize,   
                                     LPBYTE readCharBuff,    
                                     LPBYTE pStatus,         
                                     LPBYTE pDetail); 
Run Code Online (Sandbox Code Playgroud)

此回调甚至不允许数据指针,因此您根本不能使用实例方法.你是多么意想着为多个实例实现回调超出我的意义!无论如何,你可以像这样在Delphi中声明这个函数:

type
  TMICRCallback = function: Integer; stdcall;

function BiMICRSetReadBackFunction(
  nHandle: Integer;
  MicrCB: TMICRCallback;
  pReadBuffSize: PByte;
  readCharBuff: PByte;
  pStatus: PByte;
  pDetail: PByte
): Integer; stdcall; external dllname;
Run Code Online (Sandbox Code Playgroud)

要打电话给你,你需要这个:

function MICRCallback: Integer; stdcall;//not the method of a class
begin
  Result := ....
end;
.....
retval := BiMICRSetReadBackFunction(..., MICRCallback, ....);
Run Code Online (Sandbox Code Playgroud)