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

时间:2018-05-29 05:35:30

标签: c# com

我有一个由C#制作的DLL,需要从现有的原生c ++ exe调用它。 我研究了COM的基础并做了一个简单的例子。

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

我在谷歌搜索但收到的信息很少。

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

void Test2(ref float num);

生成的tlh是

HRESULT Test2 ( float * num );

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

1 个答案:

答案 0 :(得分:3)

正如汉斯所说,这个问题不是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类型库。然后,您可以打开.tlb中的oleview.exe文件来查看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#的ref和{{1}那样具体。 (大多数现代C ++编译器都假设您希望在通过引用传递之前初始化数据,如果不这样做,它们将产生错误或警告。)因此,任何定义为out或{{1}的参数在C#中定义将在C ++中简单地定义为指针。