GetFunctionPointerForDelegate

GetFunctionPointerForDelegate

我正在尝试使用具有回调机制的(C)第三方库,该回调机制缺少识别调用上下文的任何可能方法。我的主要项目在C#中,包装器是一个用于调用C库API的C++/CLI项目。

要变通解决此问题,我试图使用Marshal::GetFUnctionPointerForDelegate。这是我的C#代码:

void Init(Handler Callback)
{
    // Create a wrapper lambda in case Callback is a non-static method.
    instance.CreateBuffers((x, y) => Callback(x, y));
}

然后,在C++/CLI代码中:
void CreateBuffers(Handler^ Callback)
{
    pinCallback = GCHandle::Alloc(Callback);

    void (*callback)(int, int) = (void (__stdcall *)(int, int))Marshal::GetFunctionPointerForDelegate(Callback).ToPointer(),
    // Use 'callback' in third party library...
}

所有这一切的问题是,根据http://msdn.microsoft.com/en-us/library/367eeye0.aspx,来自Marshal::GetFunctionPointerForDelegate的函数指针是stdcall函数,但是我的C回调是cdecl。我如何在这里获得与cdecl兼容的功能?

最佳答案

我认为最简单的方法是使用UnmanagedFunctionPointer属性声明您的委托(delegate)类型为C#,以指定调用约定。

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate ...

然后,使您的C++/CLI代码接收纯本地C++函数指针。您可以传递委托(delegate)的实例,并且由于委托(delegate)具有该属性,因此编码员知道该怎么做。

这使您可以跳过GetFunctionPointerForDelegate步骤。实际上,它可以让您跳过C++/CLI层,但是我希望您不想这样做。

只要非托管代码可以看到函数指针,请确保托管代码保留对委托(delegate)的引用。如果您不这样做,那么垃圾收集器可能会将地毯从您下面拉下,因为它看不到非托管代码所拥有的引用。

当然,之前已经在此主题中进行过介绍。汉斯·帕桑特(Hans Passant)在这里有一个详细的答案,值得一读:Correct way to call a C DLL method from C#

关于c# - C#GetFunctionPointerForDelegate cdecl代替stdcall,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19740140/

10-09 03:33