2 个 COM 对象,并在另一个对象中使用其中一个对象的接口

2 COM objects and using interface from one of it in another

本文关键字:一个对象 接口 COM 对象      更新时间:2023-10-16

我有以下设置:

C# 应用和两个 COM 对象(人脸和处理器(,用 C++ 编写。
第一个 COM 对象公开接口 IFace。它在其 IDL 文件中进行了描述。
第二个 COM 对象具有接口 IProcessor,公开方法 ProcessFace(IFace* face(。

C# 应用应使用第一个 COM 对象来获取人脸,第二个对象来处理它。 这里的问题是 - 为第二个对象编写 IDL 文件的正确方法是什么,以便它可以从第一个 COM 使用接口类型的参数。

我应该以某种方式将face.idl包含在processor.idl中,还是只是将此参数保留为void*,然后在ProcessFace实现中将其转换为IFace*?

第二个COM对象应该包含第一个COM对象中的一些.h文件(用于接口共享(,但这是唯一应该包含的内容,我是否正确?

您可以使用 idl 导入指令。Windows SDK .idl文件充满了这些(如import "unknwn.idl";(。因此,在processor.idl

import "face.idl";  
[
object,
uuid(6E0537CC-232A-4E73-A625-358591CA9231),
pointer_default(unique)
]
interface IProcessor
{
HRESULT ProcessFace(IFace *pFace);
};

当然,这将需要 .idl 文件(以及生成的 .h 和各种工件,如果有的话,用于编译阶段(存在于可访问的目录中。

这里有两个选择 -importimportlib

遗憾的是,import会导致导入文件中的接口和 coclass 定义存在于已编译的.tlb文件中。这会导致注册和代理时出现各种问题。我不建议使用import.

importlib没有同样的问题。但是,这意味着您必须先将.idl编译为.tlb,然后才能导入它。从包含依赖项 (IFace( 的.idl编译.tlb。然后使用importlib关键字从包含依赖 (IProcessor( 的.idl中引用该类型库。您的第二个.idl文件将如下所示:

[...]
library ProcessorLibrary
{
importlib("FaceLibrary.tlb");
[...]
interface IProcessor
{
HRESULT ProcessFace(FaceLibrary.IFace* face)
};
}

对于importlib参数,可以使用完全限定路径或相对路径。如果使用相对路径,它将尝试使用PATH环境变量解析此文件名。如果您为此使用 Visual Studio,则可以在项目属性中设置搜索路径 - 在VC++ Directories下,将搜索路径放入Executable Directories变量中。这对应于.vcxproj文件中的ExecutablePath属性。

请注意,importlib和界面中的"FaceLibrary"是不同的。importlib中的那个是.tlb文件的名称。接口中使用的标识符是类型库名称(与第一个.idl文件中的library键一起使用的名称(。

为了编译第二个.idl文件的生成C++,您必须做两件事。第一个.tlb需要手动#import到第二个C++项目中,就像您必须在第二个.idl中使用importlib一样。然后,您需要处理C++命名空间问题。遗憾的是,midl.exe不会生成使用命名空间的代码。虽然第二个.idl文件包含FaceLibrary.IFace,但生成的C++只包含IFace。这意味着您需要不使用命名空间将第一个.tlb导入到C++项目中,或者必须使用 typedef。

不使用命名空间:

#import "FaceLibrary.tlb" no_namespace
#include "Processor_i.h"

使用命名空间:

#import "FaceLibrary.tlb"
typedef FaceLibrary.IFace IFace;
#include "Processor_i.h"

#import中相对路径的解析方式与importlib中的工作方式相同。

相关文章: