c# - 在 C++ (COM) Dll 导入中使用 C# 代码不太正确

标签 c# c++ dll com

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

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

我的 C# dll 编译*。将生成的 dll 和 tlb 文件复制到相应的 C++ 项目目录后,我在同一 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”没有成员“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 中使用您的类名而不是界面。使用 COM,所有方法都在接口(interface)上定义,而不是在实现接口(interface)的类上定义。

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

要解决此问题,请使用 CComPtr<YourInterface> .这告诉 C++ 你想通过该接口(interface)与引用的对象进行通信。这是要记住的规则:CComPtr 的类型参数和 CComQIPtr必须始终 是 COM 接口(interface)。该 COM 接口(interface)可以是显式定义的接口(interface),也可以是由 .NET 自动生成的“类接口(interface)”。

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

关于c# - 在 C++ (COM) Dll 导入中使用 C# 代码不太正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45948272/

相关文章:

c++ - boost 序列化错误 C4308 : negative integral constant converted to unsigned type

c# - 加载多个版本的 DLL

c# - 从 C++/CLI 调用 C# dll 时出现 FileNotFoundException

dll - Coldfusion COM 未注册

c++ - QML 组件和 QML 对象类型有什么区别?

c# - XSD 代码生成器的比较

c# - 为什么 Math.Tan(90) 提供一个非未定义的值?

c# - 在允许更多触摸识别之前等待 TouchesEnded 中的操作完成 - Xamarin iOS

c# - 如何删除 wpf 中动态添加的控件

c++ - "aggregate or union type that includes one of the aforementioned types"严格别名规则发生了什么?