向 COM 接口添加方法

发布于 2024-11-08 06:56:55 字数 73 浏览 0 评论 0原文

我用VS2008创建了一个ATL COM dll工作区。它已经生成了MyCom.idl接口。它是否提供了向此接口添加方法的简单方法?

I created a ATL COM dll workspace with VS2008. It has generated MyCom.idl interface. Does it provide any easy way to add a method to this interface?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

大海や 2024-11-15 06:56:55

是的,有一个选项可以做到这一点。

在此处输入图像描述

Yes, there is an option to do that.

enter image description here

我ぃ本無心為│何有愛 2024-11-15 06:56:55

如果没有向导,做到这一点并不难。我了解到添加 COM 接口方法很困难,因为我懒得在 MSDN 中查找它,所以我仔细研究了其他COM接口,并通过添加属性、方法等进行了实验。

首先,使用向导时有两个缺点,特别是在编辑现有COM接口时。首先,它很慢,尤其是当您有一个包含数十个接口的大型组件时。我坐在一个相当不错的工作站前,打开向导并完成两三个步骤比手动将方法添加到 IDL、.h 和 .cpp 文件花费的时间更长。

其次,当使用不同的 Visual Studio 和不同的向导版本时,将会生成 C++ 污垢,例如多个公共语句,而不需要任何类似的东西。不过,我建议您像向导一样行事,以便在下一个程序员再次使用该向导时不会进一步混淆 - 这会增加混淆,最终导致文件大小增加、类声明不可读和编译时间更长。只需在向导执行的相同位置插入相同类型的方法或宏即可。

所以也许你会发现我这么长时间发现的东西很有用。您可以在“了解 IDL”一文中找到更多详细信息,其中相当古老,但提供了基本的基础知识,但我不会在这里提及。

IDL 文件包含您的组件将导出的所有接口定义。因此,如果你想添加一个方法,你需要找到相应的接口定义,该定义由“interface”关键字和一个通常以大写 I 开头的名称引入。接口前面有一些用 [ 和 ] 包围的注释,我为了简单起见,将不再解释。使用 Visual Studio IDL 时,关键字将正确突出显示。典型的接口可能如下所示:

[
  object,
  uuid(0B2499FA-0D73-488C-B961-03FB8327485C),
  dual,   helpstring("IMyInterface Interface"),
  pointer_default(unique)
]
interface IMyInterface : IDispatch {
    // ... methods and properties
};

现在让我们假设 IMyInterface 仅包含一种方法,而您想要添加类似的第二个方法:

[id(1), EXCLUDE_FROM_HELP] HRESULT DoSomething([in] long newVal, [out, retval] long* pRetVal);

[ ] 括号内同样有注释。添加新方法时增加 id 注释值。另外,在参数前面添加 [in] 注释用于输入参数,[out] 注释用于将包含方法结果的参数。如果只有一个结果,您可能需要使用一种将结果用作返回值的方法。然后使用 [out, retval] 注解。

因此,当添加这样的方法时,复制上面的行,增加 ID 并更改方法名称并相应地调整参数。

请注意,[out] 参数始终必须是指针。造成这种情况的原因有几个,最明显的一个是 [in, out] 也是可能的,因此参数的结果应该写入组件内的相同内存地址,以便可以将其传递回调用者容易地。另请注意,“真实”返回值应该是 HRESULT 句柄,它将指示方法的成功或失败。

现在让我们看看 C++ 头文件的内部。我假设您会自己找到正确的文件并放置。

STDMETHOD(DoSomething)(/*[in]*/ long newVal, /*[out, retval]*/ long* pRetVal);

STDMETHOD 宏负责处理结果值(HRESULT)和调用类型。这些注释在这里无效,但为了澄清 IDL 文件中的预期用途,它们被添加为注释。不过,这些评论是可选的。请小心使用与 IDL 文件内相同的数据类型。

STDMETHODIMP CMyClass::DoSomething( /*[in]*/ long newVal, /*[out, retval]*/ long* pRetVal )
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());

    long result = GetTheResultValueFromSomewhere();
    *pRetVal = result;

    return S_OK;
}

STDMETHODIMP 是与标头中不同的宏。基本上它的作用是一样的。例如,如果您想在 MFC 对话框中使用资源,则 AFX_MANAGE_STATE 宏很重要。想象一下上面示例中的值是通过提示用户确定的。请参阅技术提示博客文章了解相关内容。

了解 IDL 机制将在发生错误时为您提供帮助,这些错误不一定是指逻辑问题,而是接口问题。它还可以让您了解界面的实际功能,这将帮助您在使用向导时避免错误,因此我鼓励任何人至少阅读一些有关它的基本信息。

It is not that hard to do this without a wizard. I learned that adding COM interface methods the hard way because I was too lazy to look it up in MSDN, so I looked closely at other COM interfaces and experimented by adding properties, methods, etc.

First of all there are two drawbacks when using the wizard, especially when editing existing COM interfaces. First it is slow, especially if you have a large component with dozens of interfaces. I sit in front of a quite decent workstation and opening the wizard and completeing the two or three steps takes longer than adding the method by hand to the IDL, .h and .cpp file.

Second is that when using different Visual Studio and thus different Wizard versions there will be generated c++ dirt like multiple public-statements without any need and stuff like that. However I recommend that you act like the wizard in order to not confuse it further if the next programmer uses the wizard again - which will increase confusion and in the end leading to increased file sizes, unreadable class declarations and longer compile times. Just insert the same type of methods or macros at the same place the wizard does.

So maybe you might find useful what I found out so long. You can find a lot more details in the article "Understanding IDL" which is quite old, but provides essential basics which I will not mention here though.

The IDL file holds all interface definitions your component will export. So if you want to add a method you need to find the corresponding interface definition which is introduced by the "interface" keyword and a name which usally starts with a capital I. The interface is preceded by some annotations surrounded by [ and ] which I will not explain for the sake of simplicity. When using Visual Studio IDL keywords will be highlighted correctly. This is how a typical interface might look like:

[
  object,
  uuid(0B2499FA-0D73-488C-B961-03FB8327485C),
  dual,   helpstring("IMyInterface Interface"),
  pointer_default(unique)
]
interface IMyInterface : IDispatch {
    // ... methods and properties
};

Now let us assume the IMyInterface contains one method only and you want to add a similar second one:

[id(1), EXCLUDE_FROM_HELP] HRESULT DoSomething([in] long newVal, [out, retval] long* pRetVal);

Again there are annotations within the [ ] brackets. When adding a new method increase the id annotations value. Also precede the parameters with the [in] annotation for input parameters, [out] for parameters which will contain the methods results. If there is only one result you may want to use a method which uses the result as return value. Then use the [out, retval] annotation.

So when adding such a method copy the line above, increase the ID and changed the methods name and adapt the parameters accordingly.

Note that the [out] parameters always must be a pointer. There are several reasons for this, the most obvious one is that [in, out] is possible too, thus the result for a parameter should be written to the same memory address inside the component so it is possible to pass it back to the caller easily. Also note that the "real" return value should be an HRESULT handle, which will indicate the success or failure of the method.

Now let us look inside the C++ header. I assume you will find the correct file and place by yourself.

STDMETHOD(DoSomething)(/*[in]*/ long newVal, /*[out, retval]*/ long* pRetVal);

The STDMETHOD macro takes care of the result value which is HRESULT and the calltype. The annoations are not valid here but for clarification of the intended usage within the IDL file they are added as comments. These comments are optional though. Be careful to use the same datatypes as inside the IDL file.

STDMETHODIMP CMyClass::DoSomething( /*[in]*/ long newVal, /*[out, retval]*/ long* pRetVal )
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());

    long result = GetTheResultValueFromSomewhere();
    *pRetVal = result;

    return S_OK;
}

The STDMETHODIMP is a different macro than in the header. Basically it does the same though. Important is the AFX_MANAGE_STATE macro if you want to use resources within an MFC dialog for instance. Imagine the value in the example above is determined by prompting the user. Read about it in the Technical Tips blog post.

Understanding the IDL mechanisms will help you as soon as errors occur which do not necessarily refer to a problem in your logic but the interface. It will also allow you to understand what the interface actually does, which will help you avoding errors when using the wizard so I encourage anyone to read at least some basic information about it.

永不分离 2024-11-15 06:56:55

如果您在类视图中展开 idl 以右键单击特定类并“添加方法”或“添加属性”,则应该有一个选项,这将引导您完成一个小向导,将该方法添加到您的接口和关联的实现中。

There should be an option if you expand the idl in the class view to right click on a specific class and 'add method' or 'add property' which will take you through a small wizard adding the method to your interface and your associated implementation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文