获取委托的IntPtr并调用

时间:2012-05-23 14:55:24

标签: c# pinvoke marshalling

要模拟来自c ++的调用,我正在尝试以下代码

    private delegate void CppFuncDelegate(string message);

    private static void Main(string[] args)
    {
        Console.WriteLine("+++ BEGIN TEST +++");

        Action<string> action = str => Console.WriteLine("Received:" + str);
        IntPtr delegatePtr = action.Method.MethodHandle.GetFunctionPointer();

        CppFuncDelegate cppFuncDelegate = (CppFuncDelegate)
           Marshal.GetDelegateForFunctionPointer(delegatePtr, 
                                                        typeof(CppFuncDelegate));
        cppFuncDelegate.Invoke("Hello");
    }

但我得到

  

检测到PInvokeStackImbalance。   调用PInvoke函数'Test!Test.Program + CppFuncDelegate :: Invoke'   堆栈不平衡。这可能是因为托管PInvoke   签名与非托管目标签名不匹配。检查一下   调用约定和PInvoke签名匹配的参数   目标非托管签名。

谁能告诉我我做错了什么?

注意:请不要告诉我做action.Invoke();这不是这个练习的内容。我想获得委托的IntPtr句柄并使用GetDelegateForFunctionPointer()然后调用返回的委托。

感谢。

1 个答案:

答案 0 :(得分:3)

您不能使用GetDelegateForFunctionPointer()来获取托管函数的委托。这来自MSDN

  

您无法将无效的函数指针传递给   GetDelegateForFunctionPointer。此外,您只能使用此功能   纯非托管函数指针的方法。你不能用这个   具有通过C ++或从中获得的函数指针的方法   GetFunctionPointer。您不能使用此方法来创建委托   从函数指针到另一个托管委托。

我不确定为什么你不能这样做,但我想这是因为微软的Common Language Runtime使用FastCall调用约定,但FastCall is not supported用于PInvoke。