Problem (simplified to make things clearer):
- 1. there is one statically-linked static.lib that has a function that increments:
extern int CallCount = 0; int TheFunction() { void *p = &CallCount; printf('Function called'); return CallCount++; }
2. static.lib is linked into a managed C++/CLI managed.dll that wraps TheFunction method:
int Managed::CallLibFunc() { return TheFunction(); }
3. Test app has a reference to managed.dll and creates multiple domains that call C++/CLI wrapper:
static void Main(string[] args) { Managed c1 = new Managed(); int val1 = c1.CallLibFunc(); // value is zero AppDomain ad = AppDomain.CreateDomain('NewDomain'); Managed c = ad.CreateInstanceAndUnwrap(a.FullName, typeof(Managed).FullName) as Managed; int val2 = c.CallLibFunc(); // value is one }
Question:
Based on what I have read in Essential .NET Vol1 The CLR by Don Box, I would expect val2 to be zero since a brand new copy of managed.dll/static.lib is loaded when CreateInstanceAndUnwrap is called. Am I misunderstanding what is happening? The static library does not seem to be respecting the appdomain boundaries since it’s unmanaged code. Is there a way to get around this issue other than by creating a brand new process for instantiating Managed?
Thank you very much everyone!
My hunch was that, as you suspected, unmanaged DLLs are loaded in the context of the process and not in the context of the AppDomain, so any static data in unmanaged code is shared among AppDomains.
This link shows someone with the same problem you have, still not 100% verification of this, but probably this is the case.
This link is about creating a callback from unmanaged code into an AppDomain using a thunking trick. I’m not sure this can help you but maybe you’ll find this useful to create some kind of a workaround.