0

I need to make a DLL written in C accessible to C# programs. I wrote a wrapper DLL in C# that wraps every C interface function. I came out with a code which is functional but eventually crashes with the following message:

Managed Debugging Assistant 'CallbackOnCollectedDelegate' has detected a problem in 'D:\WrapperTest\bin\x64\Debug\WrapperTest.exe'.

Additional information: A callback was made on a garbage collected delegate of type 'vJoyInterfaceWrap!vJoyInterfaceWrap.vJoy+WrapFfbCbFunc::Invoke'.

The part that is responsible to the crash is related to a callback function that the C# code registers with the DLL. The crash occurs when the DLL calls (or returns) from the registered callback function.

C DLL Interface:

// Definition of callback function prototype
// Parameter 1: Pointer to a data structure to be used inside the CB function
// Parameter 2: Pointer to user-defined data passed during registration
typedef void (CALLBACK *FfbGenCB)(PVOID, PVOID);

// Registration of CB function.
// Parameter cb is a pointer to the callback function.
// Parameter data is a pointer to user-defined data
VOID        __cdecl FfbRegisterGenCB(FfbGenCB cb, PVOID data);

C# Interface:

I'd like the user-defined data to be an object (rather than an IntPtr). To do that I encapsulate the user's callback function with a predefined callback function that converts IntPtr to object. Earlier during registration, I register the predefined callback function and convert the user-defined data (a C# object) to IntPtr.

// The user-defined CB function is of type FfbCbFunc
//  FfbCbFunc is defined:
public delegate void FfbCbFunc(IntPtr data,  object userData);

// The registration of the predefined callback function _WrapFfbCbFunc is done by calling
// function FfbRegisterGenCB:
       public void FfbRegisterGenCB(FfbCbFunc cb, object data)
        {
            // Convert object to pointer
            GCHandle handle1 = GCHandle.Alloc(data);

            // Apply the user-defined CB function
            _g_FfbCbFunc = new FfbCbFunc(cb);
            WrapFfbCbFunc wf = new WrapFfbCbFunc(_WrapFfbCbFunc);

            _FfbRegisterGenCB(wf, (IntPtr)handle1);
        }

Here are additional definitions and declaration:

// Placeholder for user defined callback function
private static FfbCbFunc _g_FfbCbFunc;

// predefined callback function that encapsulates the user-defined callback function
public delegate void WrapFfbCbFunc(IntPtr data, IntPtr userData);
public void _WrapFfbCbFunc(IntPtr data, IntPtr userData)
        {
            // Convert userData from pointer to object
            GCHandle handle2 = (GCHandle)userData;
            object obj = handle2.Target as object;

            // Call user-defined CB function
            _g_FfbCbFunc(data, obj);
        }
2
  • Wouldn't it be better to have the wrapper written in C and linked together with the rest of the C code into a single DLL? That way you can present the interface just as you want it to the C# application. Commented Mar 2, 2015 at 9:26
  • A wrapper written in C will not expose native C# interface such as 'object'. If I am mistaken please supply example or reference. Commented Mar 2, 2015 at 9:36

1 Answer 1

1

The wrapper callback function and its reference had to be static:

// Make wf global and static
private static WrapFfbCbFunc wf;

// Make the wrapping callback function static
public static void  _WrapFfbCbFunc(IntPtr data, IntPtr userData)
{

    object obj = null;

    if (userData != IntPtr.Zero)
    {
        // Convert userData from pointer to object
        GCHandle handle2 = (GCHandle)userData;
        obj = handle2.Target as object;
    }

    // Call user-defined CB function
    _g_FfbCbFunc(data, obj);
}

P.S.

I don't think this was such a bad question to be rewarded by a -1 vote. Personally, I just ignore questions that are not interesting.

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

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.