c# - 是否可以通过 COM 公开引用类型?

标签 c# com

我有一个由 C# 制作的 dll,需要从现有的 native C++ exe 调用它。 学习了COM的基础,做了一个简单的例子。

但是,如果一个 C# 函数有一个引用类型(尤其是用户定义类的引用)参数,我是否可以为它编写一个接口(interface)并正常工作?

我在 Google 中搜索但得到的信息很少。

更新:
我试着写了一个,看到了它生成的 tlh 文件。 C#代码是

void Test2(ref float num);

而生成的tlh是

HRESULT Test2 ( float * num );

引用类型被转换为指针类型。似乎 COM 不支持引用类型。

最佳答案

正如汉斯所说,这个问题不是关于 reference types 的.关于 passing parameters by reference .

当您在任何语言中通过引用传递参数时,您就是在显式或隐式地使用指针。在 C# 中,ref 表示“此参数将采用指向已初始化数据的指针”。 out 声明“此参数将采用指向可能已初始化或未初始化的数据的指针。”通过使用 refout,您可以使自己免受指针语义的影响。也就是说,您不必在方法签名中指定 float*。但请放心,您仍在使用指针。

COM 完全支持通过引用传递参数。下面举个例子来说明。

C#:

[Guid("962232c8-90b2-4b61-8ef3-83298901c63e")]
[ComVisible(true)]
public interface ICSCOMCLASS
{
    [DispId(1)]
    void TestInParameter(double num);

    [DispId(2)]
    void TestRefParameter(ref double num);
}

编译后,您可以在生成的程序集上运行 tlbexp.exe 以导出 COM 类型库。然后,您可以通过在 oleview.exe 中打开 .tlb 文件来查看 IDL。

[
    odl,
    uuid(962232C8-90B2-4B61-8EF3-83298901C63E),
    version(1.0),
    dual,
    oleautomation,
    custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "CSCOMLIB.ICSCOMCLASS")    
]
interface ICSCOMCLASS : IDispatch
{
    [id(0x00000001)]
    HRESULT TestInParameter([in] double num);

    [id(0x00000002)]
    HRESULT TestRefParameter([in, out] double* num);
};

注意参数上的修饰符。关于您关于ref 参数的问题,请注意TestRefParameter() 方法的参数是[in, out] double* num。这相当于 C# 的 ref double num

如果您从 C/C++ 使用此程序集或类型库(例如,通过使用 #import 语句),您将看到如下内容:

struct ICSCOMCLASS : IDispatch
{
    virtual HRESULT __stdcall TestInParameter(double num) = 0;
    virtual HRESULT __stdcall TestRefParameter(double* num) = 0;
};

COM 设计用于 C 级别及更高级别。大多数用于 C++ COM 工作的工具都被实现为使用 C(而非 C++)作为支持的基线。尽管 C++ 支持使用 & 传递引用(例如 HRESULT TestRefParameter(double& num),但 C 不支持。此外,C++ 的 & 不是与 C# 的 refout 一样具体。(大多数现代 C++ 编译器假定您希望在通过引用传递之前初始化数据,如果您这样做,它们将产生错误或警告不。)因此,在 C# 定义中定义为 refout 的任何参数将在 C++ 中简单地定义为指针。

关于c# - 是否可以通过 COM 公开引用类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50576949/

相关文章:

c# - EF 5 + SQL Server CE 4 : How to specify custom location for database file?

c# - 对话框模式在 asp.net core mvc 5 中不起作用

c# - JSON.net 异步写入文件

c# - 缓存属性与 Lazy<T>

c++ - 获取指向现有 COM 对象的指针?

安装 July'18 Updates 后的 IIS 问题

vba - 在 Excel VBA 中使用 New 关键字和调用 CreateObject 有什么区别?

c# - 具有名为 "Item"的索引器和属性的类

arrays - 如何将 OleVariant 数组有效地复制到我自己的结构中?

c# - 使用 C/C++ 学习 COM 会帮助我更好地理解 .NET 吗?