C++ interop help

R

Robert Ginsburg

I have an ATL DLL that hosts a COM object. Without managed extensions the
object compiles and works fine. Now with some assistance from Will DePalo
(on a different thread in this group) I figured out how to add CLR support
to my object and how to call into managed code. The code and the calls work
, however when the host application drops the reference to my COM object (
specifically to a class that has clr support ) the ATL framework throws an
errorr and returns RPC_S_WRONG_KIND_OF_BINDING while the reference is being
dropped.

If I comment out the clr code and remove the clr flag, the code executes
fine, If I add clr support to the module but make no clr calls I get the
error. So it appears that simply adding clr support to an ALT object is
causing the problem. The ATL class is defined as a single threaded IDispath
implementation using the ATL libraries (sample below):

class ATL_NO_VTABLE CCSharpMEVT :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CCSharpMEVT, &CLSID_CSharpMEVT>,
public ICSharpMEVT,
public IDispatchImpl<_iMEVT, &__uuidof(_iMEVT), &LIBID_MEVT, /* wMajor
= */ 56, /* wMinor = */ 3>

Has anyone seen this before ? The COM string error equates to "The string
binding is invalid."

Thanks in advance for any help or advice

Robert
 
H

Holger Grund

Robert Ginsburg said:
I have an ATL DLL that hosts a COM object. Without managed extensions the
object compiles and works fine. Now with some assistance from Will DePalo
(on a different thread in this group) I figured out how to add CLR support
to my object and how to call into managed code. The code and the calls work
, however when the host application drops the reference to my COM object
( specifically to a class that has clr support ) the ATL framework throws
an errorr and returns RPC_S_WRONG_KIND_OF_BINDING while the reference is
being dropped.

I think, I've seen something like this. You're probably calling into managed
code under the loader lock. Do you have the call stack for the exception?
IIRC the .NET DLLs ship with private symbols (anyway just grab it
from the symbol server)

From my very limited understanding you must not call into managed
code under the loader lock. However, AFAICT this is exactly what
happens when you mix native and managed code. Usually, you'd
get a hint in the debugger from the MDA. But in some cases
(which one I don't know), it just fails with an OS exception
with the code you mention.

Some of the ATL code is precompiled without /clr. There are
some globals which need initialization/destruction. For native code
that's implemented in the CRT init/cleanup code called from
the entrypoint. The constructors/destructors must not call into
managed code.

I guess, that is what happens (e.g. on ClassFactory Release).
But the MS folks would probably need a full repro case.

-hg
 
H

Holger Grund

From my very limited understanding you must not call into managed
code under the loader lock. However, AFAICT this is exactly what
happens when you mix native and managed code. Usually, you'd
get a hint in the debugger from the MDA. But in some cases
(which one I don't know), it just fails with an OS exception
with the code you mention.
In fact, it seems digged something up when I ran into the issue myself
(I guess I'm getting old).
Anyway, if my notes are correct, the managed CRT cleans up
state (e.g. atexit, dtors of globals & local statics etc.) in hooks
provided by the EE (DomainUnload and ProcessExit) event
of the AppDomain.
However, I believe, this requires some cooperation of the main
app which should call CorExitProcess if the CLR EE is
active (the VC++ CRT does that for a while).

If the host does not play nice, the runtime will eventually call
the cleanup code from the DllMain event under the loader lock.
Executing managed code might hang the process. However,
if the offending managed method has been JITted already, you get
the error above (that sounds like very odd behavior and is
probably a CLR bug)

In case anyone's interested I have a small repro case.

-hg
 
R

Robert Ginsburg

Thanks for responding so completely, yours is the only response from several
postings I made. I have come up with a work around that seems to function
well, and is pretty simple. Simply dont do it, by that I mean dont add clr
support to anything that inherits from the ATL framework. Create a "proxy"
as a different class (make sure to put it in a separate modeule and dont mix
the header or source files), add CLR support to that class, static or
instance methods seem to work fine. Call from the ATL object through the
proxy functions and it all behaves nicely.

-Robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top