【问题标题】:COM wrapper with C++/CLI and C# "as" operator带有 C++/CLI 和 C#“as”运算符的 COM 包装器
【发布时间】: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 可以为我做的所有事情。

标签: c# com c++-cli


【解决方案1】:

我意识到我需要找出 IUnknown 类型是什么,并为它 gcnew 一个相应的托管类型(一个 ref 类)。我为上面的问题简化了代码,但通常它更像下面的代码(int id 指的是正确的类型)。上面的示例代码中的错误可能导致难以回答这个问题,我很抱歉。

而且,不存在非托管类和对象之间的转换^,因此尝试创建 UnknownBase(el) 是行不通的。

public class NativeType {
    COMType* myEl;
public:
    Object^ getSomeItem(int id) { 
        IUnknown* el; 
        myEl->getItemNative(id, &el); 
        switch(id) {
            case 1: return gcnew AnotherItem(el);
            case 2: return gcnew ... 
        }
    }
};

我会尽快测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-03
    • 1970-01-01
    • 2013-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-12
    相关资源
    最近更新 更多