0

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?

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

4 Comments

@Torbjörn Kalin Do not make such changes in the code. Better point them out to the person who answered
Obviously, that's the way to do it... Also, this way, I don't have to worry about the returned char* being destructed (in case it's on the stack). Thanks!
@Coding Mash Why not? My edits do not change the correctness of the answer. I'd say it's like fixing typos/spelling errors.
@user1775315 The CppFuncThatReturnsString function does not need to be inside a class.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.