【发布时间】:2018-02-07 10:49:55
【问题描述】:
正如标题所暗示的,我很难从 C++ 调用 C# 代码。一点上下文:C# 中有一个 API 调用(在 C++ 版本的 API 中不存在),我需要将它集成到一个更大的 C++ 项目中。
我一直在阅读this SO post,并且在 COM 方法方面取得了最大的进展。
我的 C# dll 编译*。将生成的 dll 和 tlb 文件复制到相应的 C++ 项目目录后,我在同一 C++ 项目目录中打开一个 admin cmd 提示符并运行:
regasm MyFirstDll.dll /codebase /tlb
(*我将其编译为类库,程序集名称:MyFirstDll,默认命名空间:MyMethods,程序集信息... -> 使程序集 Com-Visible 被选中,Build->Register for COM interop 也被选中。)
使用对象浏览器,我可以看到我定义的类,以及具有适当参数和签名的方法。 Screenshot of it showing up in Object Browser
我遇到的问题是方法调用(而不是类)。即使该方法在对象浏览器中可见,但在我的代码中它并未被识别为对象的方法。
类“ATL::_NoAddRefReleaseOnCComPtr”没有成员“Add”
这是我的代码:
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);
}
问题是在“return adder->Add(a,b)”(NateMath.cpp)中,Add(a,b) 显示为红色,类“ATL::_NoAddRefReleaseOnCComPtr”没有成员“Add”
【问题讨论】:
-
尝试使用
CComPtr<MyFirstDll::Easy_Math>而不是CComPtr<MyFirstDll::AddClass>。 -
@HansPassant 很高兴知道!不幸的是,在将 C# AddClass.Add 代码更新为 int Add(int i, int j) 后,仍然出现相同的错误。 :(
-
@MichaelGunter 如果我对接口使用 CComPtr 而不是类,它怎么知道调用我的类的方法实现?
-
因为你
CoCreateInstance的 UUID 为AddClass,但对于 COM,你总是通过其实现的接口之一调用类的方法。 -
好的,太好了!知道为什么尝试在 C++ 对象的实例上调用 Add 时会出现空指针异常吗? NateMath nm = NateMath();长 x = nm.Add(1,2);引发读取访问冲突,“nm.adder.p was nullptr.”