[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void NativeEventCallback(IntPtr context, int eventCode);
public class MyManagedWrapper
{
private GCHandle handle;
private NativeEventCallback callbackDelegate;
public MyManagedWrapper()
{
handle = GCHandle.Alloc(this);
callbackDelegate = OnNativeEvent;
Native_CreateCppObject(
GCHandle.ToIntPtr(handle),
Marshal.GetFunctionPointerForDelegate(callbackDelegate));
}
private static void OnNativeEvent(IntPtr context, int eventCode)
{
var wrapper = (MyManagedWrapper)GCHandle.FromIntPtr(context).Target;
wrapper.HandleEvent(eventCode);
}
private void HandleEvent(int code)
{
Console.WriteLine($"Received event code: {code}");
}
~MyManagedWrapper()
{
if (handle.IsAllocated)
handle.Free();
}
[DllImport("MyNativeDll", CallingConvention = CallingConvention.Cdecl)]
private static extern void Native_CreateCppObject(IntPtr context, IntPtr callback);
}
typedef void(__cdecl* NativeEventCallback)(void* context, int eventCode);
struct CppObject
{
void* context;
NativeEventCallback callback;
void SetCallback(void* ctx, NativeEventCallback cb)
{
context = ctx;
callback = cb;
}
void TriggerEvent()
{
if (callback)
callback(context, 42); // Send event code
}
};
extern "C" __declspec(dllexport)
void Native_CreateCppObject(void* context, NativeEventCallback callback)
{
CppObject* obj = new CppObject();
obj->SetCallback(context, callback);
// Store or return obj as needed
}