【问题标题】:Calling C++ function with pointer to function in C# as parameter使用指向 C# 中的函数的指针作为参数调用 C++ 函数
【发布时间】:2013-03-31 17:03:20
【问题描述】:

我在 Native C dll 中有以下代码。

typedef void CallbackType( INT32 param1, INT32 param2 );

NATIVE_API void RegisterEventCallBack(CallbackType *callBackFunction);


//INT32 is defined as below:

typedef signed int          INT32, *PINT32;

我必须从我的 C# 代码中调用此方法。在遵循 stackflow 提供的一些解决方案之后,我尝试了这个:

委托声明:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void CallbackType(Int32 param1, Int32 param2); 

方法导入声明:

[DllImport("EtIPAdapter.dll")]
public static extern void RegisterEventCallBack([MarshalAs(UnmanagedType.FunctionPtr)]CallbackType callbackFunc);

来电:

RegisterEventCallBack(ReceivedData);

private static void ReceivedData(Int32 param1, Int32 param2)
{
    //Do something
}

但这不起作用,我收到以下错误:

对 PInvoke 函数“RegisterEventCallBack”的调用导致堆栈不平衡。这可能是因为托管 PInvoke 签名与非托管目标签名不匹配。检查 PInvoke 签名的调用约定和参数是否与目标非托管签名匹配。

我还尝试传递使用GetFunctionPointerFromDelegate(ReceivedDataDelegate) 获得的函数指针。但这也会导致同样的错误。

错误指出签名不匹配,但我没有看到任何明显的签名不匹配。请帮忙。

【问题讨论】:

  • 您可以在链接中尝试以下声明:stackoverflow.com/a/9855516/2253250 还应该检查函数原型是否正确? nirsoft.net/utils/dll_export_viewer.html 可以使用 DllExport 查看器。
  • NATIVE_API 宏是如何定义的?我认为问题在于您对 RegisterEventCallBack 函数的托管声明,而不是回调委托。您是否使用正确的调用约定?当RegisterEventCallBack 的回调参数使用cdecl 时,RegisterEventCallBack 会使用stdcallDllImport 的默认值)似乎很奇怪。

标签: c# c++ function pointers marshalling


【解决方案1】:

执行 DLLImport 时请检查调用约定 - 默认为 Winapi / StdCall。
同样重要的是,在应用程序的生命周期内,您必须在托管代码中保留对委托的引用,否则垃圾收集器将在一段时间后删除您的委托,因为垃圾收集器只能计算托管代码内的引用。我通常保留对委托的引用作为设置委托的类的静态属性。

【讨论】:

  • 谢谢。将 DLLImport 命名约定更改为“cdecl”有效。 [DllImport("EtIPAdapter.dll",CallingConvention=CallingConvention.Cdecl)] public static extern void RegisterEventCallBack([MarshalAs(UnmanagedType.FunctionPtr)]​​LogEventCallbackType pfnLogEvent);
猜你喜欢
  • 1970-01-01
  • 2011-07-11
  • 1970-01-01
  • 1970-01-01
  • 2017-11-28
  • 1970-01-01
  • 2013-09-12
  • 1970-01-01
相关资源
最近更新 更多