【问题标题】:Getting IntPtr of a delegate and invoking获取委托的 IntPtr 并调用
【发布时间】:2023-03-06 16:29:01
【问题描述】:

为了模拟来自 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() 然后调用返回的委托。

谢谢。

【问题讨论】:

  • 您是否检查过 PInvoke 签名的调用约定是否与目标非托管签名匹配?
  • @dtb CppFuncDelegate 接受一个字符串并返回 void 并且我将操作委托声明为 Action&lt;string&gt;;所以我认为他们匹配。有没有其他方法可以检查 PInvoke 签名?
  • 我不是在谈论参数,我是在谈论调用约定。

标签: c# pinvoke marshalling


【解决方案1】:

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

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

我不知道你为什么不能这样做,但我猜这是因为微软的公共语言运行时使用 FastCall 调用约定,而 FastCall is not supported 用于 PInvoke。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-06
    • 1970-01-01
    • 2013-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多