正如标题所暗示的,我很难从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>
答案 0 :(得分:0)
这是因为您尝试在CComPtr
而不是界面中使用您的班级名称。使用COM,所有方法都在接口上定义,而不是在实现接口的类上定义。
您可以CoCreateInstance(__uuidof(YourClass))
,因为目的是创建YourClass
的实例(由__uuidof(YourClass)
表示的GUID标识)。但是,C ++中的YourClass
是一个只存在的虚拟结构,因此您可以读取uuid - 从YourClass
生成的C ++中#import
的定义是空的,永远是空的。
要解决此问题,请使用CComPtr<YourInterface>
。这告诉C ++您希望通过该接口与引用的对象进行通信。以下是要记住的规则:CComPtr
和CComQIPtr
的类型参数必须始终是COM接口。 COM接口可以是显式定义的接口,也可以是&#34;类接口&#34;这是由.NET自动生成的。
说到类接口:如果您使用ClassInterfaceType.AutoDual
而不是None
,则可以使用CComPtr<_YourClass>
(注意前导下划线 - _YourClass
是类接口,而YourClass
将是类。我建议你按照现有的方式进行。