calling managed dll from native dll and keeping a static ref

What issues should I be aware of when doing the following:

End scenario: Native dll needs to hold a static reference to a managed class (written in c#) throughout the lifetime of the native dll.

I have written a slight wrapper in managed c++ (technically c++/cli) in whidbey.

This all seems to work fine and dandy, but there always seems to be a "gotcha" in the managed c++ world. When I compile I get this warning:

Warning 1 warning C4251: 'RequestHandler::wrapperClass' : struct 'gcroot<T>' needs to have dll-interface to be used by clients of class 'RequestHandler

1. Can this be ignored in this case since the native class shouldn't touch the wrapper class variable (that represents the c# object) inside of the managed wrapper

The c++ wrapper class is written as:
#define EXP __declspec ( dllexport )

#ifdef _MANAGED

# define GCHANDLE(T) gcroot<T>

#else

# define GCHANDLE(T) intptr_t

#endif

class EXP RequestHandler

{

public:

// wrapped properties/methods

RequestHandler();

void TestMethod();

GCHANDLE(Authorization::RequestProxy^) wrapperClass;

};

It's used as such from the native dll as such:

static RequestHandler handler;

inside a method in the native dll:
handler.TestMethod();


2. Should RequestHandler be instantiated in dllmain What kind of loader lock issues can there be with initializing a managed wrapper inside of a native dllmain I did read somewhere to be careful with this even in whidbey and the loader lock problem greatly improved upon.


Thanks!
-----
Adam Tuliper
www.secure-coding.com



Answer this question

calling managed dll from native dll and keeping a static ref

  • Robbie W

    Great, Thanks Jonathan. Since this is an isapi dll calling into a mixed mode c++ dll, I can prob just initialize it in GetFilterVersion for the isapi filter rather than DllMain. Any other issues you can think of in this particular scenario or does it seem to be on the right path
    Thanks for your input!
    -----
    Adam Tuliper
    www.secure-coding.com

     


  • Chitra

    scratch that, I received a nice loadlock dialog when trying to delete the object in DllMain (although it worked one time outside of debugger and failed another in the debugger - maybe by design ), so when (how) should this object be deleted so as to not leak a GCHANDLE if it can't be done in DllMain Just out of curiosity, when do static initializers get called If I declare the object as a static instance, would this take care of the problem Sorry, the more I read the more questions come up : )

    -----
    Adam Tuliper
    www.secure-coding.com


  • Waqas H. Mehr

    1) Ignoring C4251 is usually fine, especially if the class it refers to is a specialization of a class template. The reason that this is OK is that class templates are normally fully defined in a header file so there is less risk of the implementation of the class being split across the DLL boundary: which is the point of this warning.

    2) No: the default constructor for gcroot calls GCHandle::Alloc which will cause the CLR to spin-up: something you really want to avoid happening in DllMain as it can lead to the infamous loader-lock problem.

  • Hilton.Giesenow

    Ok, so now the next question is cleanup in this case.
    DllMain it seems should be avoided, but if this is where a library is notified its about to be unloaded, shouldn't the cleanup of the managed object happen here Is that case OK to delete a managed object in DllMain since the runtime has already started at this point when DLL_PROCESS_DETACH is called

    Thanks,
    -----
    Adam Tuliper
    www.secure-coding.com

  • senfo

    Adam: this seems the right approach. The load-lock problem is associated with DllMain. As long as DllMain does not call managed code (either directly or indirectly) you should be OK.

  • calling managed dll from native dll and keeping a static ref