Question

I need to call a c++ callback function from c# that returns a String. When I try with the code below the application crashes hard (with a message saying that it may be due to a corruption of the heap).

Here's the c++ code:

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

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

And here's the c# code:

public class CSharp
{
    private delegate string CppFuncDelegate();

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

Do I have to do some kind of marshaling magic with the string before returning it?

Was it helpful?

Solution

Why are you using function pointers in the first place? Just pass an instance of the delegate to the C# code:

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();
    }
}

I think you may need to put CppFuncThatReturnsString inside a class.

OTHER TIPS

I found the answer on 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());
    }
}

That is, pass it as an IntPtr and marshal it into a string on the C# side.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top