Absolute COM Confusion - C # interop with early binding

I struggled with VStudio, Google and other tools and websites all day and did not find a solution - HELP !!

I have two COM interfaces (pure COM, without ATL):

IMyClassFactory and IMyClass with corresponding implementations

I want to use them with C # BUT without registering a COM server with regsvr32. I expose the Factory class with CoRegisterClassObject and can successfully create IMyClass objects with CoCreateInstance from unmanaged code.

So C # interop ...

I created a .NET wrapper with tlbimp myComServer.tlb and downloaded it as a reference to my C # client.

Then, when I try to create an instance of IMyClass, I get:

An unhandled exception of type 'System.InvalidCastException' occurred in COMTestClient.exe

Additional information: Unable to cast COM object of type 'MyComServerLib.MyClass' to interface type 'MyComServerLib.IMyClass'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{9F8CBFDC-8117-4B9F-9BDC-12D2E6A92A06}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

Now I have added traces to the QueryInterface, and the only cases when I return E_NOINTERFACE is when it requests any of the marshal-related interfaces or for IManagedObject.

How to fix it?

EDIT: My IDL file:

import "unknwn.idl";

[
    object, 
    uuid(...), 
    nonextensible,
    pointer_default(unique)
]
interface IMyClass : IUnknown
{
    HRESULT(SetFirstNumber)(long nX1);

    HRESULT(SetSecondNumber)(long nX2);

    HRESULT(DoTheAddition)([out,retval] long *pBuffer);
};

[
    uuid(...)
]
library MyLib
{
    importlib("stdole2.tlb");

    [
        uuid(...)
    ]
    coclass IMyClassImpl
    {
        [default] interface IMyClass;
    };
}
+3
source share
2 answers

You need to either allow the sorting of your interface (that is, marking it as "not local" in the .idl file so that it falls into the type library and the proxy server), or aggregate if you go this way.

To combine the FTM, I did something like this:

#define DECLARE_FTM() \
protected: CComPtr<IUnknown> _m_Marshal; \
DECLARE_GET_CONTROLLING_UNKNOWN() \
public: HRESULT FinalConstruct() \
{ return CoCreateFreeThreadedMarshaler(GetControllingUnknown(),&_m_Marshal); }

#define COM_INTERFACE_ENTRY_FTM() COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal,_m_Marshal.p)

Then on your COM card:

BEGIN_COM_MAP(Blah)
    COM_INTERFACE_ENTRY(IBlah)
    COM_INTERFACE_ENTRY_FTM()
END_COM_MAP()
DECLARE_FTM()

, ATL .. - , QueryInterface FTM, IMarshal.

, FTM -, - , . , - , .

, [Franci Penov], , . , , , ( midl ) dll / ( / dll), .

/.

+4
  • . .
  • oleautomation. , typelib, -, midl. (: oleautomation OLE, , IDispatch).
+1

Source: https://habr.com/ru/post/1719462/


All Articles