nativecpp

I have some questions on C++/CLI issue. Let me explain my situation:

I have an existing native COM dll that contains my logic. It has been tested and works fine with native C++ client using CoCreateInstance. I would like to add a new logic and notice that BCL has a class that I can use. So I add a new source file and header which I compile with /clr since I need to use one of BCL classes (actually, at this point, it is just an empty shell). When I tried to CoCreateInstance in my native client, it couldní»t create. But if I go back to my COM dll project and take out the /clr in my new source file, it works fine. After some debugging, I found out the problem and have been able to fix the issue. However, I would like to get more details about my solutions and would appreciate any comments. My two solutions are:

1) Because the existing COM was created before VS 2003/2005, it uses BEGIN_OBJECT_MAP.
The reason I was having problem was that it 'delays' calling InternalDllMain and therefore delays calling
InitInstance. The default InitInstance calls CComModule's Init which actaully initialize
factory function pointers in the array. By using OBJECT_ENTRY_AUTO, it
resolves the program because the factory pointers is defined in the data
segment. So, in one sense, I didn't really solve the root of the problem(
which is NOT calling InternalDllMain ). I am just calling/initializing
factory function pointers somehwere else. Is my observation correct What happen if my code needs to call InitInstance


2) Because of my own question in #1, I tried to solve it another way:
a) Declare a dummy managed class.
b) Create a static bool (gloaded) initialized to false
c) Modified DllGetClassObject as follow:


STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
if (!gloaded)
{
dummyclass dc;
gloaded = true;
}
return _Module.GetClassObject(rclsid, riid, ppv);
}

This seems to work and it looks like it has some undocumented (I think)
behavoir in that the InternalDllMain won't get call until some managed class
got created as you can see from PostDllMain. I found a way to fix it but is it OK

Thanks



Re: Visual C++ Language C++/CLI problems/issues

nativecpp

I just wanted to clarify my solution #2. Source file for dummyclass is actually compile w/o clr. However, its constructor call my dummy managed class's static function as shown below:

// compile unmanaged (i.e w/o clr)

#include "dummyclass.h"

#include "mclass1.h"

dummyclass::dummyclass()

{

ManagedClass::ClrLoad(); // <= this is calling managed class

}

The reason is that the main cpp where DllRegisterServer, etc is in must be compiled w/o clr. Otherwise, it won't register. Therefore, my dummyclass must be compiled w/o clr !

I hope to hear some comments soon

Thanks





Re: Visual C++ Language C++/CLI problems/issues

Brian Kramer

You're probably further along the problem than we can be. I'm trying to understand your fundamental question. Is it to compile certain bits of code as unmanaged There's a #pragma managed that accomplishes this.



Re: Visual C++ Language C++/CLI problems/issues

nativecpp

For my COM project , I do NOT use #pragma managed at all.

For my solution #1,

However, I do have a newly created source file (empty shell) that is compiled with /clr. The rest of the source file is compiled w/o clr. I guess because I have one source file that is compiled with /clr, it (dll) becomes mixed mode even though this particular file does NOT contain #pragma managed or #pragma unmanaged.

For my soultion #2, I created a dummy native class whose constructor would call dummy managed class's static function to force to 'kick' in some managed initialization (I think).

I just would like to get more details about this issue. BTW, it is very easy to reproduce this. Just create a dummy COM (unmanaged) and later add a new soruce compile with /clr and you can see that it cannot CoCreateInstance.

Thanks





Re: Visual C++ Language C++/CLI problems/issues

nobugz

I hesitate to respond but it sounds like you're running into a problem that MSFT created by trying to fix the dreaded "loader lock" issue. That issue would be prone to gum up the works when you create an ATL COM object that is compiled with /clr. I see DllMain() in vc\atlmfc\src\mfc\dllmodul.cpp specifically checking if /clr is enabled. I see vc\atlmfc\src\mfcm\postdllmain.cpp calling InternalDllMain() through the PostDllMain variable.

How this all ties together to mess up your code is quite unclear to me. Short from: "the loader lock issue isn't fixed yet". I've seen the lock just by trying to use OLE2A...





Re: Visual C++ Language C++/CLI problems/issues

nativecpp

I don't think I am experiencing loader lock issue. As I mentioned earlier, my orginal problem (not able to CoCreateInstance) was due to the fact that I was using BEGIN_OBJECT_MAP. Once I changed that to OBJECT_ENTRY_AUTO, it works fine due to the reason I indicated earlier. As far as I can tell, it looks like VC++ delays calling InternalDllMain (may be trying to reduce loader lock ). My own desire is to understand fully what is going on and to see if my solution #1 & #2 are valid (it seems ok as it resolve CoCreateInstance issue).

May be someone from VC++ or anyone for that matter could let develoeprs know what is going on

Thanks





Re: Visual C++ Language C++/CLI problems/issues

abccpp

Hi all,

Just want to add additional info why I think it isn't loader lock issue. If we look at DllMain in dllmodule.cpp as shown below, you can see that the code checks the mixedmode flag (_mixedModuleStartup) and will skip InternalDllMain if the flag is true. The comment indicated that it is done in PostDllMain. My main reason to post is to get some answers on the following:

1) Is my observation correct
2) Are my two solutions valid
3) Is PostDllMain created to reduce Loader Lock
3) If I need to call InitInstance and yet I don't to add code to create some dummy managed class, how do I do that

BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (__mixedModuleStartup)
{
// Skip initialization in mixed mode (done in PostDllMain, see afxdisp.h)
if (dwReason == DLL_PROCESS_ATTACH)
{
// save the module instance
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
pModuleState->m_hCurrentInstanceHandle = hInstance;
#ifdef _AFXDLL
// restore previously-saved module state
VERIFY(AfxSetModuleState(AfxGetThreadState()->m_pPrevModuleState) ==
&afxModuleState);
DEBUG_ONLY(AfxGetThreadState()->m_pPrevModuleState = NULL);
#endif
return TRUE;
}
else if (dwReason == DLL_PROCESS_DETACH)
{
return TRUE;
}
else
{
return InternalDllMain(hInstance, dwReason, lpReserved);
}
}
else
{
return InternalDllMain(hInstance, dwReason, lpReserved);
}
}





Re: Visual C++ Language C++/CLI problems/issues

nativecpp

Hi all,

I just wanted to find out if anyone would kind enough to response to my questions/observations before this post get to the bottom of the stack. Actually, before I posted, I did a lot of digging but couldn't get the answers I need. I don't know if someone from VC++ team would response and give some info since I believe probably they would know the VC++ compiler implementation more than anyone of us.

BTW, abccpp == nativecpp So, I also posted the last entry.

Thanks





Re: Visual C++ Language C++/CLI problems/issues

Ale Contenti

Hi [abc|native]cpp :-),

I'll take a look at this post later today and reply to your questions.

Thx!

Ale Contenti

VC++ Libraries Team





Re: Visual C++ Language C++/CLI problems/issues

nobugz

Shoot, I was working on a long post several days ago but it didn't make it to the thread. I might have abandoned it. It's kinda fuzzy now, as most ATL topics tend to get, but the first thing to try it to replace you CComModule with a CAtlDllModuleT. There's been drastic changes in the ATL object model and it looks like CAtlDllModuleT was invented to delay the call to DllMain...






Re: Visual C++ Language C++/CLI problems/issues

nativecpp

Hi nobugz,

Changing to CAtlDllModuleT would force me to use OBJECT_ENTRY_AUTO which I know would solve the CoCreateInstance problem because the macro would inject a custome segment to initialize 'factory pointers/table'. But it doesn't really resolve the main issue which is that it never calls my app's InitInsstance. It is possible that I may need to do some custom initialization. I believe it is being called once some 'managed stuff' got kicked in.

Hi Ale,

I looks forward to your findings/comments. This problem has been bugging for a while and is driving me nut :-(

Thanks





Re: Visual C++ Language C++/CLI problems/issues

Ale Contenti

Ok, I read the entire thread more carefully, now...

Like you observed, in DllMain (from dllmodul.cpp) we check if __mixedModuleStartup and we don't call InternalDllMain. We do call it later, after managed initalization, using PostDllMain.

Not sure if you noticed how PostDllMain works: it's a small static object which is initialized in a specific CRT init segment, which happens to be after all static managed objects have been initialized (look into postdllmain.cpp for details).

Why do we do this Because we assume that your CWinApp is compiled managed. Remeber that static managed objects are initialized after DllMain is called (while static native objects are initialized after before DllMain).

So, if CWinApp is managed, we cannot call InitInstance until after all managed objects have been initialized. That's why we wait to call InternalDllMain.

The problem with your code is that the module is mixed, but CWinApp is native.

If you compile the CWinApp definition with /clr, InitInstance should be called in the right order.

This is somewhat related to loader lock, because you cannot initialize or call managed code during DllMain: that's why we avoid initializing CWinApp during DllMain...

I hope this shed some light on the problem.

I'm sure you'll have more questions/thoughts!

Let us know!

Thx!

Ale Contenti

VC++ Libraries Team





Re: Visual C++ Language C++/CLI problems/issues

Brian Kramer

Can't a debug build of MFC assert on the unsupported mixed scenario you described



Re: Visual C++ Language C++/CLI problems/issues

nativecpp

Hi Ale,

Thanks for the additional info.

1) Yes, I did notice about the special #pragma in postdllmain.cpp.

2) As for your suggestion, I added /clr in my main dll where CWinApp, DllGetClassObject, etc are declared/defined. However, it still does NOT CoCreateInstance successfully and that it did NOT go to the break point in InitInstance. Am I missing something

Thanks





Re: Visual C++ Language C++/CLI problems/issues

Ale Contenti

Hi nativecpp,

Do you have repro steps for this issue

I'll try it out on my box.

thx! ale.