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

Is it possible to expose a reference type through COM?

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

但是,如果一个C#函数有一个引用类型(特别是用户自定义的class'引用)参数,我可以为它写一个接口,并且工作正常吗?

我在 Google 中进行了搜索,但得到的信息很少。

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

void Test2(ref float num);

而生成的tlh是

HRESULT Test2 ( float * num );

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

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

当您在任何语言中通过引用传递参数时,您就是在显式或隐式地使用指针。在 C# 中,ref 表示 "this parameter will take a pointer to data which has already been initialized." out 表示 "this parameter will take a pointer to data which may or may not have already been initialized." 通过使用 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++ 编译器假定您希望在通过引用传递之前初始化数据,如果您不这样做,它们将产生错误或警告。)因此,任何定义为 ref 或 [=14= 的参数] 在 C# 定义中将在 C++ 中简单地定义为指针。