【发布时间】:2016-07-29 07:23:41
【问题描述】:
我正在用 C++/CLI 编写一个 COM 包装器,并为如何解决问题而苦苦挣扎。
在 C# 方面,我将调用这样的代码:
var item = myWrappedObj.getSomeItem() as AnotherItem;
C++/CLI 托管端持有一个指向非托管对象的指针:
public ref class MyWrapped {
NativeType* unManagedEl;
public:
Object^ getSomeItem() { return unManagedEl->getSomeItem(); }
...
};
C++/CLI 非托管端完成这项工作,假设返回包装在 UnknownBase 本机类中的 IUnknown*
public class UnknownBase {
IUnknown* myEl;
public:
UnknownBase(IUnknown* el) { myEl = el; }
...
};
public class NativeType {
COMType* myEl;
public:
Object^ getSomeItem() {
IUnknown* el; myEl->getItemNative(&el); return UnknownBase(el);
}
};
现在,接口中有许多“AnotherItem”类型(上面的第一个代码部分),我正在考虑创建派生自 UnknownBase 等的托管 + 非托管包装器。然后呢?我将如何获得 C#“as”运算符的相应代码?从 MSDN 我了解到 dynamic_cast 是对应的运算符,将被称为“as”,但是包装了 IUnknown 指针,我不能单独依赖 dynamic_cast。我只是试图找出 dynamic_cast 是否会使用类的类型转换运算符(以便我可以手动检查单独的类型转换运算符中的类型相等性),但我认为不是?
我在 C# 端有一个庞大的代码库,它使用编组 + tlbimp'ed 接口,所以我试图保持接口完全相同(以替换“从暗面和错误”编组接口),因此我想出了双包装器(实际上,分开的命名空间等来做更多的魔法)。
【问题讨论】:
-
由于包装纸太多,您进入了这个泡菜。 COMType 已经是一个非常好的类型,你通过将它包装在一个无类型的类中使它变得无用。您可以通过添加更多包装器再次包装它,现在必须以正确的方式复制 COMType。但是删除包装器是更好的方法。至少杀死 UnknownBase 并考虑这是否有用,C# 已经可以在没有任何帮助的情况下使用 COMType。
-
恐怕COMType来自idl/header,C#看不到。
-
IDL 的主要用途是生成可以 Tlbimp 的类型库。当然,您也可以生成 .h。使用 /tlb 选项运行 midl.exe 以确保它确实是一条死路,它可能是。杀掉 UnknownBase,至少 .h 文件给你一个已知的基础。
-
但是在这里使用 C++/CLI 设计包装器(以及这个问题)的全部原因是不使用您所描述的。我已经有一个来自 tlbimp 的互操作 dll,并将我的 C# 代码基于那个无用的场所。有问题,现在我正在编写自己的包装器 - 自己完成 tlbimp / interop.dll 或 p/invoke 可以为我做的所有事情。