Need help resolving AccessViolationException with C#/C interop

164 views Asked by At

I need some help fixing a persistent AccessViolationException.

Given a c signature like this

struct message {
    char *topic;
    void *payload;
    int payloadlen;
};

__declspec(dllexport) void callback_set(struct data *dat, void (*on_publish)(struct data *, void *, const struct message *));

I have this C#

    public struct message 
    {
        public string topic;
        public IntPtr payload;
        public int payloadlen;
    };


    /* INTEROP ACCESS */
    public delegate void on_publish(IntPtr dat, IntPtr usrData, IntPtr messageData);

    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    public extern static void callback_set(IntPtr dat, IntPtr callback);

    /* IMPLEMENTATION OF OUR on_publish*/
    public static void MessageHandler(IntPtr dat, IntPtr usrData, IntPtr messageData)
    {
        var instance = (message)Marshal.PtrToStructure(messageData, typeof(message));
        string test = instance.topic; // <-- this is successfully received
        Console.WriteLine("message rec " + test);
    } //<-- as soon as I exit, the dll blows up with access violation


    /* REGISTERING MESSAGEHANDLER AS ON_PUBLISH */
    public static void RegisterMessageHandler(IntPtr dat) //<-- I promise, the pointer I send here is valid and not modified
    {
        messageHandler = new on_publish(MessageHandler);
        messageHandlerPtr = Marshal.GetFunctionPointerForDelegate(messageHandler);
        callback_set(dat, messageHandlerPtr); //<-- if I do not call this, everything works, no ADE
        Console.WriteLine("message handler registered");
    }
    //just tried to move to scope in order to retain their managed memory loc
    private static IntPtr messageHandlerPtr;  
    private static on_publish messageHandler;

When running, and making sure a message should be received - I get the correct string for the topic but as soon as MessageHandler returns, I get the dreaded exception.

Things I've tried:

  • Change CallingConvention
  • Use on_publish instead of IntPtr in managed callback_set definition
  • Probably more things in desperation that should not have an impact

Any help much appreciated!

I can share a zip of the project if anyone can help - it will be BSD licensed just like Mosquitto which I'm trying to interop with.

1

There are 1 answers

0
AlexanderBrevig On BEST ANSWER

I ended up creating a C++/CLI project to wrap the C project to .NET.

I found it much easier to manage the unmanaged code using C++, and I ended up with a nice interop to C# as my class became .NET accessible.

I would recommend this path, and will do it myself - the next time I need to integrate C# with a C lib.