C++项目中调用C#DLL的的方式

C++项目中调用C#DLL的的方式

在C++中调用C#编写的DLL,通常需要借助COM(Component Object Model)技术或者通过C++/CLI(C++托管扩展)来实现。以下是两种常见的方法:

方法一:使用COM技术

1.在C#中创建COM可见的类库

在C#项目中,确保类库项目属性中的"Make assembly COM-Visible"选项被勾选。这会为类库生成一个GUID,并将其注册为COM组件。

例如,创建一个C#类库项目MyCSharpLibrary,并添加一个类MyClass:

下面展示一些 内联代码片

javascript 复制代码
using System;
using System.Runtime.InteropServices;

[ComVisible(true)]
[Guid("YOUR-GUID-HERE")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMyClass
{
    void MyMethod();
}

[ComVisible(true)]
[Guid("YOUR-CLASS-GUID-HERE")]
public class MyClass : IMyClass
{
    public void MyMethod()
    {
        Console.WriteLine("Hello from C#!");
    }
}

生成DLL后,使用regasm工具将其注册为COM组件:

下面展示一些 内联代码片

下面展示一些 内联代码片

javascript 复制代码
regasm MyCSharpLibrary.dll /codebase

2.在C++中调用COM组件

在C++代码中,通过COM接口调用C#类库中的方法:

下面展示一些 内联代码片

javascript 复制代码
#include <iostream>
#import "MyCSharpLibrary.tlb" // 导入类型库文件

int main()
{
    CoInitialize(NULL); // 初始化COM库

    IMyClassPtr myClass(__uuidof(MyClass)); // 创建COM对象
    myClass->MyMethod(); // 调用方法

    CoUninitialize(); // 释放COM库
    return 0;
}

注意:需要确保C++项目中链接了ole32.lib和oleaut32.lib。

方法二:使用C++/CLI

C++/CLI是一种混合编程语言,允许在C++代码中直接使用托管代码(如C#代码)。

创建C++/CLI项目

在Visual Studio中创建一个C++/CLI项目,例如MyCppCliWrapper。

在C++/CLI中引用C# DLL

在C++/CLI项目中添加对C# DLL的引用。

创建一个托管类来封装C#类的功能:

下面展示一些 内联代码片

javascript 复制代码
// MyCppCliWrapper.h
#pragma once

using namespace System;

public ref class MyCppCliWrapper
{
public:
    void CallCSharpMethod();
};
// MyCppCliWrapper.cpp
#include "MyCppCliWrapper.h"
#include "MyCSharpLibrary.h" // 引用C#类库

void MyCppCliWrapper::CallCSharpMethod()
{
    MyCSharpLibrary::MyClass^ myClass = gcnew MyCSharpLibrary::MyClass();
    myClass->MyMethod();
}

3.在C++代码中调用C++/CLI封装

在C++代码中调用C++/CLI封装的函数:

下面展示一些 内联代码片

javascript 复制代码
#include <iostream>
#include "MyCppCliWrapper.h"

int main()
{
    MyCppCliWrapper^ wrapper = gcnew MyCppCliWrapper();
    wrapper->CallCSharpMethod();
    return 0;
}

方法三:使用P/Invoke(适用于C#导出非托管接口)

如果C# DLL中导出了非托管接口(例如通过DllImport或[UnmanagedCallersOnly]),可以直接在C++中通过函数指针调用。

在C#中导出非托管接口

使用[UnmanagedCallersOnly]属性导出方法:

下面展示一些 内联代码片

javascript 复制代码
using System;
using System.Runtime.InteropServices;

public class MyClass
{
    [UnmanagedCallersOnly(EntryPoint = "MyMethod")]
    public static void MyMethod()
    {
        Console.WriteLine("Hello from C#!");
    }
}

在C++中调用导出的函数

加载DLL并获取函数指针:

下面展示一些 内联代码片

javascript 复制代码
#include <iostream>
#include <windows.h>

typedef void (*MyMethodFunc)();

int main()
{
    HMODULE hModule = LoadLibrary("MyCSharpLibrary.dll");
    if (hModule)
    {
        MyMethodFunc myMethod = (MyMethodFunc)GetProcAddress(hModule, "MyMethod");
        if (myMethod)
        {
            myMethod();
        }
        FreeLibrary(hModule);
    }
    return 0;
}

总结

COM技术:适合需要跨语言调用的场景,但需要额外的注册和配置。

C++/CLI:适合需要在C++中直接调用托管代码的场景,代码更简洁。

P/Invoke:适合C#导出非托管接口的场景,调用方式更接近原生C++。

相关推荐
handler019 小时前
从零实现自动化构建:Linux Makefile 完全指南
linux·c++·笔记·学习·自动化
我头发多我先学11 小时前
C++ 模板全解:从泛型编程初阶到特化、分离编译进阶
java·开发语言·c++
星星码️11 小时前
C++选择题练习(一)
开发语言·c++
小苗卷不动14 小时前
OJ练习之疯狂的自我检索者(简单)
c++
LUVK_14 小时前
第七章查找
数据结构·c++·考研·算法·408
迷途之人不知返14 小时前
vector
c++
khalil102014 小时前
代码随想录算法训练营Day-31贪心算法 | 56. 合并区间、738. 单调递增的数字、968. 监控二叉树
数据结构·c++·算法·leetcode·贪心算法·二叉树·递归
小苗卷不动14 小时前
进程与线程的核心区别
c++
啊我不会诶15 小时前
2024ICPC西安邀请赛补题
c++·算法
ZenosDoron15 小时前
keil软件修改字体,Asm editor,和C/C++ editor的区别
c语言·开发语言·c++