我强烈建议您创建一个IDL 文件来设计您的 COM 接口。
鉴于您在回答中的示例,一个相当小的 IDL 文件可能是这样的:
import "oaidl.idl";
[object,
uuid(1f6efffc-0ac7-3221-8175-5272a09cea82),
dual,
oleautomation]
interface IStreamFrame : IDispatch {
[propget]
HRESULT Width([out, retval] long *pWidth);
[propget]
HRESULT Height([out, retval] long *pHeight);
[propget]
HRESULT Buffer([out, retval] SAFEARRAY(byte) *pBuffer);
};
[uuid(1f6efffc-0ac7-3221-8175-5272a09cea83)]
library ContosoStreamFrame {
importlib("stdole32.tlb");
interface IStreamFrame;
};
然后,您可以使用midl.exe
C/C++ 接口生成 .h、用于 C/C++ 链接的 CLSID 和 IID 常量的 _i.c、用于 RPC 注册的 dlldata.c、带有代理和存根编组的 _p.c 以及.tlb 通常是 .idl 文件的解析表示。这在文档中有更好的描述。
编辑:似乎没有办法避免 C/C++ 文件生成。
EDIT2:我刚刚找到了一种解决方法,nul
用作您不想要的输出文件。例如,以下命令仅生成file.tlb
:
midl.exe /header nul /iid nul /proxy nul /dlldata nul file.idl
注意:如果您的IStreamFrame
接口不打算跨进程使用,请将local
属性添加到接口。
在 C/C++ 中,您可以使用生成的特定文件或#import
TLB 文件。在 .NET 中,您可以tlbimp.exe
在生成 .NET 程序集的 TLB 文件上运行。
tlbexp.exe
如果您的项目以 .NET 为中心,您也可以使用。但是,这将要求您了解 .NET COM 注释以及它们在 IDL 方面的含义,因此我不确定以牺牲大量装饰为代价以另一种语言保存一个额外的源文件是否有任何好处接口和类定义中的噪音。如果您想在源代码级别完全控制类和接口,并且希望在 .NET 代码上尽可能简单(阅读、优化可用性和速度),这可能是一个不错的选择。
最后,您可以通过创建项目在 Visual Studio 中自动执行所有这些操作。如果您使用 IDL 方法,请添加一个自定义构建步骤,该步骤调用midl.exe
并使tlbimp.exe
依赖项目依赖此项目以获得正确的构建顺序。如果您使用 .NET 方法,请添加一个自定义构建步骤,该步骤调用tlbexp.exe
并使依赖的 C/C++ 项目依赖于该项目。
编辑:如果您不需要从中生成的 C/C++ 文件midl.exe
,您可以将del
命令添加到特定输出文件的自定义构建步骤中。
EDIT2:或使用上述nul
解决方法。
当类型库已经存在时,一种常用的方法是使用 Visual Studio 将其导入 .NET。但是这样一来,如果您更新 IDL 文件,您必须记住重新生成 TLB 并再次导入它。