以前我在后期构建事件中使用tlbimp.exe为仅本机的c ++ COM项目生成托管互操作程序集。
我希望直接从C#托管项目中引用c ++项目。
我将C ++项目更改为具有公共语言运行时支持,即/ clr
我删除了C#端的旧互操作引用并添加了对C ++项目的引用后,接口和类显示为空的静态结构。
C ++方面:
// 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 [来自元数据]:
[CLSCompliant (false)]
[NativeCppClass]
public static struct IRow
{
}
有什么缺失的提示?
答案 0 :(得分:3)
__ interface是Visual Studio 2002引入的一组语言扩展(称为“属性”)的一部分。目的是能够直接在C ++源代码中定义您通常在MIDL中定义的内容并使ATL更易于使用让它自动“理解”属性。
当您使用/ clr构建C ++源代码并使用tlbimp导入生成的类型库时,IRow在tlbimp生成的interop-assembly中定义。它的定义完全基于使用__interface生成的COM类型库;也就是说,它是一个带有ComImport属性的普通.NET接口。
使用/ clr构建C ++源代码时,C ++编译器为IRow发出.NET元数据,表示它是本机类型,因为即使应用了/ clr,它仍然是COM接口。要从C#中正确使用IRow,您必须继续使用从tlbimp(或手动)创建的互操作程序集中使用IRow,或者使用C ++ / CLI将IRow(以及实现它的类)转换为.NET类型。或者,您可以在C ++ / CLI中定义一些直接使用COM类型的包装类,但是我没有看到这样做的好处。
以下是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; }
};
我怀疑这对于你现有的COM对象可能不是一个微不足道的重写,所以我可能会坚持使用COM互操作,除非你有令人信服的理由不这样做。