一篇就够【C++生成的dll给c#用的方法,使用 C++ 创建 DLL 并供 C# 调用】

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

一、方法1:使用DllImport实现dll导入

1. 方法1:使用 C++ 创建 DLL及C++ DLL 代码示例

MyLibrary.cpp

#include "MyLibrary.h"
// 一个简单的导出函数
extern "C" __declspec(dllexport) int AddNumbers(int a, int b) {
    return a + b;
}

MyLibrary.h

#pragma once
extern "C" __declspec(dllexport) int AddNumbers(int a, int b);

2. 创建 DLL

方法:

  1. 使用 Visual Studio 创建一个新的 DLL 项目: 选择 Win32 或 x64。 项目类型选择 动态链接库 (DLL)。
  2. 将上述代码添加到项目中。 编译项目,生成 .dll 文件和 .lib 文件。

3. 在 C# 中调用 DLL

C# 调用代码示例

using System;
using System.Runtime.InteropServices;
class Program
{
    // 导入 C++ DLL 中的函数
    [DllImport("MyLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern int AddNumbers(int a, int b);
    static void Main()
    {
        int result = AddNumbers(10, 20);
        Console.WriteLine($"Result: {result}");
    }
}

关键点:
DLL 文件路径: 确保 MyLibrary.dll 在 C# 项目的执行目录下,或者将其路径添加到环境变量 PATH 中。
函数声明一致性: 确保 DllImport 中的函数签名与 C++ 中的定义完全一致。
调用约定: 使用 CallingConvention.Cdecl,因为默认情况下,C++ 使用 Cdecl 调用约定。

二、方法2:使用引用方式添加dll:可行的替代方案:封装为 namespace.dll

问题:为什么不能直接引用 C++ DLL?:
答案:C++ 的 DLL 是基于非托管代码的,没有 .NET 元数据,C# 无法直接识别。
需要通过 P/Invoke(Platform Invocation Services)或 C++/CLI 桥接来调用。

需要怎么弄?

2.1 创建并封装非托管DLL

首先: 使用 C++/CLI 封装非托管 DLL
MyLibrary.h

#pragma once

extern "C" __declspec(dllexport) int AddNumbers(int a, int b);

MyLibrary.cpp

#include "MyLibrary.h"

int AddNumbers(int a, int b) {
    return a + b;
}

其次:创建非托管 C++ DLL
代码:非托管 C++ DLL

最后:生成非托管 DLL:

方法: 在 Visual Studio 中创建一个 Win32 项目,选择 动态链接库 (DLL) 类型。
添加以上代码,编译后生成 MyLibrary.dll 和对应的 MyLibrary.lib 文件。

2.2. 创建 C++/CLI 项目,可以理解是中间层

步骤:

在 Visual Studio 中,创建新的项目:
    项目类型:Class Library (.NET Framework)
    项目语言:C++
    启用 CLR 支持(默认在 C++/CLI 项目中已经启用)。

添加对非托管 C++ DLL 的引用:
    在项目属性中,配置链接器。
        附加依赖项:添加 MyLibrary.lib。
        附加库目录:设置为非托管 DLL 的生成路径。

2.2.1 编写 C++/CLI 封装代码

ManagedLibrary.h

#pragma once
// 使用托管代码提供的命名空间
namespace MyNamespace {
    public ref class Calculator {
    public:
        static int Add(int a, int b);
    };
}

ManagedLibrary.cpp

#include "ManagedLibrary.h"
#include "../MyLibrary/MyLibrary.h" // 引入非托管 DLL 的头文件
namespace MyNamespace {
    int Calculator::Add(int a, int b) {
        return AddNumbers(a, b); // 调用非托管的函数
    }
}

2.2.2 编译托管库

方法:编译项目,生成 ManagedLibrary.dll
此 DLL 是托管程序集,包含 .NET 元数据。
它可以直接被 C# 项目引用。

2.2.3 在 C# 中使用托管库

引用托管 DLL:

将 ManagedLibrary.dll 添加到 C# 项目中作为引用。
确保 MyLibrary.dll(非托管 DLL)位于 C# 项目的输出目录下,或添加到系统路径。

C# 调用示例:

Program.cs

using System;
using MyNamespace; // 引入 C++/CLI 提供的命名空间
class Program
{
    static void Main()
    {
        int result = Calculator.Add(10, 20); // 调用 C++/CLI 封装的函数
        Console.WriteLine($"Result: {result}"); // 输出结果:30
    }
}

关键点解释

1.C++/CLI 桥接:
    C++/CLI 项目通过普通 #include 调用非托管 C++ 函数。
    C++/CLI 提供托管接口,暴露给 C# 使用。

2.非托管 DLL 的部署:
    非托管 DLL 必须与 C# 应用程序一起发布。
    确保非托管 DLL 在 C# 程序运行时可被加载(通常放在输出目录)。

3.托管和非托管混合:
    C++/CLI 自动处理托管代码与非托管代码的交互,开发者只需关注逻辑。

完整文件结构示例

Solution
├── NonManagedLibrary (非托管项目)
│ ├── MyLibrary.h
│ ├── MyLibrary.cpp
│ ├── MyLibrary.dll (编译生成)
│ └── MyLibrary.lib (编译生成)
├── ManagedLibrary (C++/CLI 项目)
│ ├── ManagedLibrary.h
│ ├── ManagedLibrary.cpp
│ └── ManagedLibrary.dll (编译生成)
└── CSharpApplication (C# 项目)
├── Program.cs
├── ManagedLibrary.dll (引用)
└── MyLibrary.dll (复制到输出目录)
优点

简化了 C# 调用非托管 DLL 的过程。
提供标准的 .NET 接口,符合 C# 的开发习惯。
C++/CLI 自动管理托管和非托管代码的桥接,减轻开发负担。

适用场景

需要封装大量复杂的非托管 C++ API。
希望通过 .NET 提供统一的接口给 C# 和其他托管语言使用。

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值