【问题标题】:Return string from c++ function pointer invoked from c#从 c# 调用的 c++ 函数指针返回字符串
【发布时间】:2012-10-26 12:09:22
【问题描述】:

我需要从 c# 调用一个返回字符串的 c++ 回调函数。当我尝试使用下面的代码时,应用程序会严重崩溃(一条消息说这可能是由于堆损坏造成的)。

这是 c++ 代码:

static String^ CppFunctionThatReturnsString()
{
    return gcnew String("From C++");
}

void main()
{
    CSharp::CSharpFunction(IntPtr(CppFunctionThatReturnsString));
}

这是 c# 代码:

public class CSharp
{
    private delegate string CppFuncDelegate();

    public static void CSharpFunction(IntPtr cppFunc)
    {
        var func = (CppFuncDelegate)Marshal.GetDelegateForFunctionPointer(cppFunc, typeof(CppFuncDelegate));
        func(); // Crash
    }
}

在返回之前我是否必须对字符串进行某种编组魔术?

【问题讨论】:

    标签: c++-cli marshalling function-pointers managed managed-c++


    【解决方案1】:

    你为什么首先使用函数指针?只需将委托的实例传递给 C# 代码:

    C++:

    static String^ CppFunctionThatReturnsString()
    {
        return gcnew String("From C++");
    }
    
    void main()
    {
        CSharp::CSharpFunction(new CSharp::CppFuncDelegate(CppFuncThatReturnsString));
    }
    

    C#:

    public class CSharp
    {
        private delegate string CppFuncDelegate();
    
        public static void CSharpFunction(CppFuncDelegate d)
        {
            d();
        }
    }
    

    我认为您可能需要将 CppFuncThatReturnsString 放在一个类中。

    【讨论】:

    • @Torbjörn Kalin 不要在代码中进行此类更改。最好将它们指出给回答的人
    • 显然,这就是这样做的方法......而且,这样,我不必担心返回的 char* 被破坏(以防它在堆栈上)。谢谢!
    • @Coding Mash 为什么不呢?我的编辑不会改变答案的正确性。我会说这就像修复拼写错误/拼写错误。
    • @user1775315 CppFuncThatReturnsString 函数不需要在类中。
    【解决方案2】:

    我在this ten year old page找到了答案。

    c++:

    static const char* __stdcall CppFunctionThatReturnsString()
    {
        return "From C++";
    }
    
    void main()
    {
        CSharp::CSharpFunction(IntPtr(CppFunctionThatReturnsString));
    }
    

    c#:

    public class CSharp
    {
        private delegate IntPtr CppFuncDelegate();
    
        public static void CSharpFunction(IntPtr cppFunc)
        {
            var func = (CppFuncDelegate)Marshal.GetDelegateForFunctionPointer(cppFunc, typeof(CppFuncDelegate));
            Marshal.PtrToStringAnsi(func());
        }
    }
    

    也就是说,将其作为 IntPtr 传递并在 C# 端将其编组为字符串。

    【讨论】:

      猜你喜欢
      • 2021-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多