我有一个由C#制作的DLL,需要从现有的原生c ++ exe调用它。 我研究了COM的基础并做了一个简单的例子。
但是,如果C#函数有一个引用类型(特别是用户定义的类'引用)参数,我可以为它编写一个接口,并且工作正常吗?
我在谷歌搜索但收到的信息很少。
更新
我试着写一个并看到它生成的tlh文件。
C#代码是
void Test2(ref float num);
生成的tlh是
HRESULT Test2 ( float * num );
引用类型转换为指针类型。似乎COM不支持引用类型。
答案 0 :(得分:3)
正如汉斯所说,这个问题不是reference types。这是关于passing parameters by reference。
当您通过引用以任何语言传递参数时,您显式或隐式地使用指针。在C#中,ref
表示“此参数将指向已经初始化的数据”。 out
声明“此参数将指向可能已初始化的数据的指针。”通过使用ref
或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类型库。然后,您可以打开.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 ++中简单地定义为指针。