为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
慕沐林林 2021-07-02 13:00:43
我有一个由 C# 制作的 dll,需要从现有的本机 C++ exe 调用它。研究了COM的基础,做了一个简单的例子。但是,如果一个 C# 函数有一个引用类型(尤其是用户定义类的引用)参数,我可以为它编写一个接口,并且工作正常吗?我在谷歌搜索,但得到的信息很少。更新:我试着写一个并看到它生成的 tlh 文件。C# 代码是void Test2(ref float num);生成的 tlh 是HRESULT Test2 ( float * num );引用类型被转换为指针类型。似乎 COM 不支持引用类型。
查看完整描述

1 回答

?
红糖糍粑

TA贡献1815条经验 获得超6个赞

正如汉斯所提到的,这个问题与引用类型无关。这是关于通过引用传递参数。


当您在任何语言中通过引用传递参数时,您都显式或隐式地使用了指针。在 C# 中,ref声明“此参数将采用指向已初始化数据的指针”。out声明“此参数将采用指向可能已或可能尚未初始化的数据的指针。” 通过使用refor out,您可以屏蔽指针语义。也就是说,您不必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 类型库。然后,您可以通过以 .zip.tlb格式打开文件来查看 IDL oleview.exe。


[

    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和那样具体out。(大多数现代 C++ 编译器假设您希望在通过引用传递之前初始化数据,并且它们会产生一个错误或警告,如果你不)。因此,定义为任何参数ref或out在C#中的定义将被简称C ++定义为指针。


查看完整回答
反对 回复 2021-07-10
  • 1 回答
  • 0 关注
  • 117 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信