在C ++(COM)中使用C#代码Dll导入工作不正常

时间:2017-08-29 21:02:12

标签: c# c++ dll com

正如标题所暗示的,我很难从C ++调用C#代码。一点上下文:在C#中有一个API调用(在API的C ++版本中不存在),我需要将它集成到一个更大的C ++项目中。

我一直在阅读this SO post,并用COM方法取得了最大的进展。

我的C#dll编译*。将生成的dll和tlb文件复制到相应的C ++项目目录后,我在同一个C ++项目目录中打开一个admin cmd提示符并运行:

regasm MyFirstDll.dll /codebase /tlb

(*我将其编译为类库,程序集名称:MyFirstDll,默认命名空间:MyMethods,程序集信息... - >选中程序集Com-Visible,Build->还检查COM interop的注册。)

使用对象浏览器,我能够看到我定义的类,以及具有适当的args和签名的方法。 Screenshot of it showing up in Object Browser

我遇到的问题是方法调用(而不是类)。即使该方法在对象浏览器中可见,但在我的代码中,它不被识别为对象的方法。

类“ATL :: _ NoAddRefReleaseOnCComPtr”没有成员“添加”
这是我的代码:

MyFirstDll C#项目:

using System;
using System.Runtime.InteropServices;
//

namespace MyMethods
{
    // Interface declaration.
    [Guid("8a0f4457-b08f-4124-bc49-18fe11cb108e")]
    [ComVisible(true)]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface Easy_Math
    {
        [DispId(1)]
        long Add(long i, long j);
    };
}
namespace MyMethods
{
    [Guid("0cb5e240-0df8-4a13-87dc-50823a395ec1")]
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    [ProgId("MyMethods.AddClass")]
    public class AddClass: Easy_Math
    {
        public AddClass() { }
        [ComVisible(true)]

        public long Add(long i, long j)
        {
            return (i + j);
        }
    }
}

NateMath.h:

#include <atlcomcli.h> 
#import "MyFirstDll.tlb"

class NateMath
{
public:
    NateMath(void);
    ~NateMath(void);
    long Add(long a, long b);

private:
    CComPtr<MyFirstDll::AddClass> adder;
};

NateMath.cpp:

#include "stdafx.h"
#include <atlcomcli.h>
#import "MyFirstDll.tlb"
#include "NateMath.h"

NateMath::NateMath(void)
{
    CoInitialize(NULL);
    adder.CoCreateInstance(__uuidof(MyFirstDll::AddClass));
}

NateMath::~NateMath(void)
{
    CoUninitialize();
}
long NateMath::Add(long a, long b) {
    return adder->Add(a,b);
}

问题在于“返回加法器 - &gt;添加(a,b)”(NateMath.cpp)添加(a,b)显示红色,类“ATL :: _ NoAddRefReleaseOnCComPtr”没有成员“添加”< / p>

1 个答案:

答案 0 :(得分:0)

这是因为您尝试在CComPtr而不是界面中使用您的班级名称。使用COM,所有方法都在接口上定义,而不是在实现接口的类上定义。

您可以CoCreateInstance(__uuidof(YourClass)),因为目的是创建YourClass的实例(由__uuidof(YourClass)表示的GUID标识)。但是,C ++中的YourClass是一个只存在的虚拟结构,因此您可以读取uuid - 从YourClass生成的C ++中#import的定义是空的,永远是空的。

要解决此问题,请使用CComPtr<YourInterface>。这告诉C ++您希望通过该接口与引用的对象进行通信。以下是要记住的规则:CComPtrCComQIPtr的类型参数必须始终是COM接口。 COM接口可以是显式定义的接口,也可以是&#34;类接口&#34;这是由.NET自动生成的。

说到类接口:如果您使用ClassInterfaceType.AutoDual而不是None,则可以使用CComPtr<_YourClass>(注意前导下划线 - _YourClass是类接口,而YourClass将是类。我建议你按照现有的方式进行。