You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取Delphi类对象中成员方法的指针?

解决Delphi类成员方法无法作为JsNativeFunction回调的问题

当将原本可直接作为JsNativeFunction的普通函数改为TTestObject的成员方法后,直接通过@TestObject.Window_Atob获取指针会触发编译器错误E2036,核心原因是Delphi非静态类成员方法隐含一个Self参数,其函数签名与JsNativeFunction不匹配,无法直接转换。

以下是两种可行的解决方案:

方案一:使用静态成员方法

静态类成员方法不包含隐含的Self参数,函数签名可以与JsNativeFunction对齐。如果需要访问实例数据,可以将对象实例存入CallbackState参数中:

type
  TTestObject = class
  public
    // 定义静态成员方法,严格匹配JsNativeFunction的签名和调用约定
    class function Window_Atob(callee: JsValueRef; isConstructCall: bool; arguments: PJsValueRef; argumentCount: Word; callbackState: Pointer): JsValueRef; stdcall;
  end;

// 实现静态方法
class function TTestObject.Window_Atob(callee: JsValueRef; isConstructCall: bool; arguments: PJsValueRef; argumentCount: Word; callbackState: Pointer): JsValueRef; stdcall;
var
  Obj: TTestObject;
begin
  // 从CallbackState中取出对象实例
  Obj := TTestObject(callbackState);
  // 调用实例逻辑
  Result := Obj.YourInstanceLogic(callee, isConstructCall, arguments, argumentCount);
end;

// 注册回调时传入静态方法地址和实例
JsSetCallback(Instance, 'atob', @TTestObject.Window_Atob, TestObjectInstance, True);

方案二:使用普通包装函数作为中间层

定义一个普通的stdcall函数作为包装层,将对象实例通过CallbackState传递,在包装函数中调用目标实例方法:

type
  TTestObject = class
  public
    // 定义实例方法,去掉callbackState参数(因为实例本身就是Self)
    function Window_AtobImpl(callee: JsValueRef; isConstructCall: bool; arguments: PJsValueRef; argumentCount: Word): JsValueRef;
  end;

// 实现实例方法
function TTestObject.Window_AtobImpl(callee: JsValueRef; isConstructCall: bool; arguments: PJsValueRef; argumentCount: Word): JsValueRef;
begin
  // 这里写原本的业务逻辑
end;

// 定义包装函数,严格匹配JsNativeFunction签名
function Window_AtobWrapper(callee: JsValueRef; isConstructCall: bool; arguments: PJsValueRef; argumentCount: Word; callbackState: Pointer): JsValueRef; stdcall;
begin
  // 将CallbackState转换为TTestObject实例,调用实例方法
  Result := TTestObject(callbackState).Window_AtobImpl(callee, isConstructCall, arguments, argumentCount);
end;

// 注册回调时传入包装函数地址和实例
JsSetCallback(Instance, 'atob', @Window_AtobWrapper, TestObjectInstance, True);

关键注意事项

  • 所有作为回调的函数必须严格遵循stdcall调用约定,与JsNativeFunction的定义一致;
  • 不要直接尝试获取非静态成员方法的地址,其隐含的Self参数会导致签名不匹配,触发编译错误。

内容的提问来源于stack exchange,提问作者Pascal Bergeron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 21:23:30