A question about importing a C++ .dll file

I wrote a test importing program, calling a C++ .dll in a C# WPF. I was trying to set a callback function in the member function of an exported struct. The code is below:

//////////////////code start //////////////////////////
typedef void (CALLBACK* LogHandler)(const char*);
extern “C” {
struct NativeManager
{
public:
const char* ( * GetModuleName)();
void ( * SetLogHandler)(LogHandler handler);//This member function cannot set the callback function
class CTestManager* TestManager;
};

_declspec(dllexport) NativeManager* CreateNativeManager();
_declspec(dllexport) void ReleaseNativeManager();
_declspec(dllexport) void ExSetLogHandler(LogHandler handler);// This exported function can set the right callback function

}
//////////////////code end//////////////////////////

My purpose is to set a C# callback function to C++ code, only _declspec(dllexport) void ExSetLogHandler(LogHandler handler) can do it right.
Why can’t NativeManager::SetLogHandler set the callback function? Calling NativeManager::SetLogHandler resulted in wrong input parameters’ signatures.

FYI a “struct” in C/C++ always has public fields so you don’t need “public:”.
Also instead of passing back a C struct to C# just return the ptr of the function for testing.
If you want to pass back a struct pointer make sure to mark your C# copy with a “[StructLayout(LayoutKind.Sequential)]”

Use “GetDelegateForFunctionPointer<TDelegate>” to get a delegate for your C function pointer in C#.
https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.getdelegateforfunctionpointer?view=netframework-4.8

Thanks for your reply. I have no problem with this NativeManager struct pointer. My C# code can get this struct pointer successfully from the .dll file. And the member function pointer GetModuleName works fine in C#. Also SetLogHandler can work, only the input parameter LogHandler handler has a different signature in C#. I’m wondering what makes the signature different, because ExSetLogHandler and NativeManager::SetLogHandler have exactly the same input parameter in C#.

I don’t know what all you’re doing in your code but seems like maybe you want something like this:

typedef void (*LogHandler)(const char*);
struct NativeManager
{
	const char* (*GetModuleName)();
	LogHandler handler;
	class CTestManager* TestManager;
};

Also stackoverflow is a much better place for these kinds of questions.

Thx for your reply again. I was trying to figure out all kinds of ways for marshaling data between .net and c++, and I’m doing a blog on this.
Finally, I find out the solution for this member function pointer signature issue:
C# should Invoke this c++ function pointer as the __stdcall style because of that CALLBACK in LogHandler represents “__stdcall”. So the code may be like this:

struct NativeManager
{
const char* (GetModuleName)();
void (_stdcall
SetLogHandler)(LogHandler handler);
struct CTestManager* TestManager;
};

.NET Foundation Website | Blog | Projects | Code of Conduct