文章目录
一、方法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
方法:
- 使用 Visual Studio 创建一个新的 DLL 项目: 选择 Win32 或 x64。 项目类型选择 动态链接库 (DLL)。
- 将上述代码添加到项目中。 编译项目,生成 .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# 和其他托管语言使用。

2362

被折叠的 条评论
为什么被折叠?



