locked
Problems with an managed callback from unmanaged c++ dll RRS feed

  • Question

  • Hi. I'll be as shor as possible, since English is not my first language. I have a unmanaged dll where I call the following method:

    [DllImport("GPIXFS.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern int GPIXFS_AsyncExecute(int hGpiXfs, int lComand, IntPtr lpCmdData, int dwTimeout, int hWnd, ref uint ulRequest);
    
    

    The AsyncExecute method calls an callback function which signature is
    typedef (CALLBACK * GPIXFS_FN_NOTIF ) (LPGPIXFS_NOTIF); 
    


    The callback function must return an int to signalize the action was taken:

    0 Processed
    1 Non Processed
    3 Maintenance
    4 Normal

    I declared the delegate as follows

     

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate Int32 GPIXFSNotification(ref GPIXFS_NOTIF lpNotif);

    public event GPIXFSNotification onNotifDeleg;

    And this is the body of the delegate function:

    public CDNAdapter()
    {
    this.onNotifDeleg += new GPIXFSNotification(gpi_onNotifDeleg);
    Open();
    }
    
    public Int32 gpi_onNotifDeleg(ref GPIXFS_NOTIF lpNotif)
    {
    return 0;
    }
    

    The problem is, every time I run the code, I got an access violation error and the app crashes after the line 'return 0' (at the '}' to be more specific.) 

    I have googled a lot and have found out that the problem evolves using Garbage Collector, but this is a new world for me. Could anybody give me some direction?

    Please, don't ask me why using ref parameters, wasnt me the person who coded the c dll.

    Thanks in advance

    Tuesday, June 28, 2011 7:02 PM

Answers

  • The garbage collector releases objects which are no longer accessible from managed code.

    Passing a function pointer to an unmanaged code involves creating a delegate and getting a function pointer from the delegate.

    Since unmanaged code is, by definition, not managed, the garbage collector doesn't know that the delegate is still needed and will release it as soon as the managed code doesn't need it. Calling the callback after the delegate is released causes an access violation.

    To prevent this, you have to store the delegate somewhere until it is no longer required.

    • Marked as answer by Lie You Wednesday, July 6, 2011 1:54 AM
    Wednesday, June 29, 2011 7:18 AM

All replies

  • The garbage collector releases objects which are no longer accessible from managed code.

    Passing a function pointer to an unmanaged code involves creating a delegate and getting a function pointer from the delegate.

    Since unmanaged code is, by definition, not managed, the garbage collector doesn't know that the delegate is still needed and will release it as soon as the managed code doesn't need it. Calling the callback after the delegate is released causes an access violation.

    To prevent this, you have to store the delegate somewhere until it is no longer required.

    • Marked as answer by Lie You Wednesday, July 6, 2011 1:54 AM
    Wednesday, June 29, 2011 7:18 AM
  • Hi Louis

    Sorry for the delay.

     

    Apparently everything went fine when we changed the callback function from

    public Int32 gpi_onNotifDeleg(ref GPIXFS_NOTIF lpNotif)


    to

    public static Int32 gpi_onNotifDeleg(IntPtr pNotif)
    

    Dont know if the problem is the function not being static or the parameter must be IntPtr intead of ref.

     

    Thanks again

    Wednesday, July 6, 2011 5:05 PM
  • That alone wouldn't solve the issue. Either you did something else (store the delegate somewhere) or you just got lucky and the delegate had not yet been release at the time it was called.
    Monday, July 25, 2011 12:27 PM
  • I'm pretty sure that for static objects the GC doesn't clean them up until the appdomain requires collection.
    Monday, July 25, 2011 12:52 PM

  • That alone wouldn't solve the issue. Either you did something else (store the delegate somewhere) or you just got lucky and the delegate had not yet been release at the time it was called.

    Oh yeah! I'm sorrey, there are something else. I've put the delegate as static also.

     

    public static event GPIXFSNotification onNotifXFS;
    


    Monday, July 25, 2011 1:28 PM
  • The only requirement is that the delegate you create must be accessible at the time the callback is called. It is not necessary to be stored in a static field.

    Note that the callback being a static method doesn't add anything for this problem. It's the delegate pointing to the method that needs to be stored.

    Monday, July 25, 2011 4:14 PM
  • Hi, i'm traying to use the GPIXFS.dll from DllImport Attrubute in C#, but i don't know how to do it, i mean, if i would like to print a sample text in a xfs printer, How do i do it, any suggestions?P.D. English is not my first language, sorry :P, i hope you can help me please.

    Monday, January 30, 2012 6:29 PM