开发者

COM classes show as empty struct on C# side with /clr support enabled

开发者 https://www.devze.com 2023-02-12 11:03 出处:网络
Previously I was using tlbimp.exe in a post-build event开发者_开发技巧 to generate a managed interop assembly for a native-only c++ COM project.

Previously I was using tlbimp.exe in a post-build event开发者_开发技巧 to generate a managed interop assembly for a native-only c++ COM project.

I wish to directly reference the c++ project from a C# managed project.

I changed the C++ project to have Common Language Runtime Support i.e. /clr

After I removed the old interop reference on the C# side and added the reference to the C++ project, interfaces and classes are showing up as empty static structs.

C++ side:


// IRow
[
    object,
    uuid("2D52A372-1094-4A59-AF6B-A874E587FA98"),
    dual,   helpstring("IRow Interface"),
    pointer_default(unique)
]
public __interface IRow : IDispatch
{
  [id(DISPID_VALUE), helpstring("method Item")]
    HRESULT Item([in] LONG index, [out,retval] VARIANT* val);
};

C# side [from metadata]:


[CLSCompliant (false)]
[NativeCppClass]
public static struct IRow
{
}

Any hints at to what's missing?


__interface is part of a set of language extensions (called "attributes") introduced with Visual Studio 2002. The intent was to be able to define directly in C++ source code what you normally would define in MIDL and make ATL easier to use by having it automatically "grok" the attributes.

When you build your C++ source code without /clr and use tlbimp to import the generated type library, IRow is defined in the interop-assembly generated by tlbimp. Its definition is based entirely off of the COM type library generated from the use of __interface; that is to say, it's a normal .NET interface with a ComImport attribute.

When you build your C++ source code with /clr, the C++ compiler emits .NET metadata for IRow to denote that it is a native type as it remains a COM interface even with /clr applied. To properly use IRow from C#, you must either continue to use IRow from an interop assembly created with tlbimp (or hand-rolled), or convert IRow (and the classes that implement it) to .NET types using C++/CLI. Alternatively, you could define some wrapper classes in C++/CLI that directly use the COM types, but I don't see much benefit in doing so.

Here's what the the interface and an implementor might look like in C++/CLI:

public interface class IRow
{
    System::Object^ Item(int index);
};

public ref class ImplementedRow : public IRow
{
public:
   System::Object^ Item(int index) { return nullptr; }
};

I suspect this may not be a trivial rewrite for your existing COM objects, so I would probably just stick with COM interop unless you have a compelling reason not to.

0

精彩评论

暂无评论...
验证码 换一张
取 消