在C++(COM)中使用C#代码Dll导入不能正常工作
正如标题所暗示的,我很难从C++调用C#代码。一点上下文:在C#中有一个API调用(在C++版本的API中不存在),我需要将它集成到一个更大的C++项目中。在C++(COM)中使用C#代码Dll导入不能正常工作
我一直在阅读this SO post,并且用COM方法取得了最大进展。
我的C#的DLL编译*。所产生的DLL和TLB文件复制到相应的C++项目目录后,我打开管理员CMD在同一个C++项目目录提示符,然后运行:
regasm MyFirstDll.dll /codebase /tlb
(*我编译它作为一个类库,大会名称: MyFirstDll,默认命名空间:MyMethods,程序集信息... - >使汇编Com-Visible被选中,Build-> Register for COM interop也被选中。)
使用对象浏览器,我能够看到类我定义了一个具有适当的参数和签名的方法。 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);
}
问题是在“返回加法器 - >添加(a,b)”(NateMath.cpp)添加(a,b)显示红色与类“ATL :: _否AddRefReleaseOnCComPtr”没有成员“添加”
这是因为您正尝试在CComPtr
而不是界面中使用您的班级名称。使用COM,所有方法都是在接口上定义的,而不是在实现接口的类上定义的。
您可以CoCreateInstance(__uuidof(YourClass))
,因为意图是创建一个YourClass
(由__uuidof(YourClass)
表示的GUID标识)的实例。但是,C++中的YourClass
是仅存在的虚拟结构,因此您可以读取uuid - 从#import
生成的C++中的YourClass
的定义为空,并且始终为空。
要解决此问题,请使用CComPtr<YourInterface>
。这告诉C++你想通过该接口与被引用的对象进行通信。这里有一条规则要记住:CComPtr
和CComQIPtr
的类型参数必须是总是是一个COM接口。该COM接口可以是一个明确定义的接口,也可以是由.NET自动生成的“类接口”。
的类接口说到:如果您用过ClassInterfaceType.AutoDual
代替None
,你可以使用一个CComPtr<_YourClass>
(注意前导下划线 - _YourClass
是类接口,而YourClass
将是一流的,我会建议做的。然而,你已经有了这种方法
这是不正确的,他通过明确声明接口来做到了这一点。他忘了使用它。好的建议可能应该包括建议使用#import自动生成的智能指针类型,在这种情况下应该命名为'Easy_MathPtr'。 –
@HansPassant啊,谢谢。我忘记了类接口是'_YourClass',而不是'YourClass'。至于使用'CComPtr'和'_com_ptr',这完全取决于消费开发者。如果他们在现有的ATL项目中使用它,没有理由选择生成'_com_ptr'而不是'CComPtr'。事实上,这样做意味着你有一个额外的异常类型来处理('_com_error')。 –
尝试使用'CComPtr'而不是'CComPtr '。 –
@HansPassant这很好知道!不幸的是,在更新C#AddClass将代码添加到int Add(int i,int j)中,仍然出现同样的错误。:( –
@MichaelGunter如果我使用CComPtr而不是类,它将如何知道调用我的类的实现方法? –