I am trying to call a C++ wrapper function from dotnet service on Linux the first time.
C++ code:
extern "C" std::string myfunc(int a, int b){
std::string mystring = funcB(a, b);
return mystring;
}
c# code:
public string myCsharpFunc getA(int a, int b){
return callMyFunc(a, b);
}
[DllImport("xxxx.so", EntryPoint ="myfunc", CallingConvention= CallingConvertion.Cdecl)]
private static extern string callMyfunc(int a, int b);
The dotnet service is running fine and I am able to do a test GET. I could also run into myFunc and the return from funcB looked correct. But everything crashed when mystring is returned with a segmentation fault (core dump). It seems like even if I made mystring returned as "test", the program crashed the same way. What did I miss?
If you compile this code using clang 13, you get a very interesting warning:
(An easy way to compile your code against a ton of compilers and other tools to see what various compilers and tools think about your code is https://godbolt.org/).
You are using
extern "C"to say "this function should be linked and made available in a way that it can be called from any C-like API". But sincestd::stringis a C++ class, it isn't something that can be used from C.extern "C", despite what it suggests, doesn't really work.And when you try and invoke this function through .NET it doesn't work and fails in all sorts of interesting way.
You should use a data type that has a valid C-linkage. Probably a
char*here. The type marshalling in .NET will automatically convert a Cchar*to a C#stringand the other way around.There's some subtlety to memory allocation too. If you return a
char *that was allocated viamalloc, you will have to take special care tofreeit correctly. See pinvoke: How to free a malloc'd string? for more details.