SWIG入门 - c++ 同 c# 的混合编程

本文介绍了如何使用SWIG在C#中调用C++编写的DLL。通过创建C++ DLL项目,编写接口定义文件,配置SWIG工具生成C#接口,然后在C#项目中调用生成的接口进行测试,展示了SWIG的基本用法。

同C#的混合编程-SWIG入门

最后更新日期:2014-04-18  by kagula

环境:Windows8.1 64bits(英文版)、Visual Studio 2013 Update1(英文版)、SWIG Win 3.0.0

正文:

         做小项目直接《C#调用C++写的Native DLL》工作量也能接受,但是,当接口变得很复杂这个方式就不经济。

         SWIG是个免费开源的C++接口生成工具,可以支持20多种常见计算机编程语言,可以帮助我们快速生成C++的外部接口,C#的调用接口。这篇文章就是介绍SWIG的最基本使用。

        

部署SWIG运行环境

从www.swig.org下载SWIG Win 3.0.0并解压缩到D:\SDK (你也可以选择其它目录),为系统配置环境变量SWIG_HOME,如下图。


为测试SWIG工具的功能,准备C++工程和C#工程

我们需要个含C++和C#工程的Solution来测试我们的SWIG工具,下图是新建Solution后的文件清单。


先建立C++工程

在Visu

<think>我们正在处理的是如何在Visual Studio 2019环境下使用SWIGC++代码转换为C#的详细过程。用户已经提供了之前的回答,其中包含了一个通用的SWIG使用指南,但现在需要针对VS2019的具体步骤。 步骤概览: 1. 安装SWIG并配置环境变量。 2. 创建C++项目(生成DLL)。 3. 编写SWIG接口文件(.i文件)。 4. 使用SWIG生成C#包装代码和C++包装器代码。 5.C++项目中集成包装器代码并编译生成DLL。 6. 创建C#项目并添加生成的C#文件,时将DLL放置在合适的位置。 7.C#C++代码。 详细步骤: 步骤1:安装SWIGSWIG官网(http://www.swig.org/download.html)下载Windows版本的SWIG(例如swigwin-4.1.1.zip),解压到某个目录(例如C:\swigwin-4.1.1)。然后将该目录添加到系统环境变量PATH中,以便在命令行中可以直接使用swig命令。 步骤2:创建C++ DLL项目 在Visual Studio 2019中: - 新建一个项目,选择“动态链接库(DLL)”模板(在Windows桌面向导中)。 - 项目名称:例如“MathLibrary”。 - 添加头文件(math_utils.h)和源文件(math_utils.cpp),内容参考之前的示例: math_utils.h: ```cpp #pragma once class MathUtils { public: double add(double a, double b); static int factorial(int n); }; ``` math_utils.cpp: ```cpp #include "math_utils.h" double MathUtils::add(double a, double b) { return a + b; } int MathUtils::factorial(int n) { return (n <= 1) ? 1 : n * factorial(n-1); } ``` - 确保项目配置为生成DLL(在项目属性->常规->配置类型中确认)。 步骤3:创建SWIG接口文件 在C++项目目录下,创建一个名为“math_utils.i”的文件,内容如下: ```swig %module math_utils %{ #include "math_utils.h" %} %include "math_utils.h" ``` 步骤4:生成包装代码 打开“开发者命令提示符 for VS 2019”(这样可以使用cl.exe等命令),切换到项目目录。 运行以下命令: ```bash swig -c++ -csharp -outdir .\Generated math_utils.i ``` 这将在当前目录下的Generated文件夹中生成C#文件(MathUtils.cs, MathUtilsPINVOKE.cs等),时生成一个C++包装器源文件math_utils_wrap.cxx。 步骤5:将包装器集成到C++项目 - 将生成的math_utils_wrap.cxx添加到C++项目的源文件中。 - 在项目属性中,确保包含目录设置正确(包含当前目录等,以便找到math_utils.h)。 - 注意:math_utils_wrap.cxx中会包含Python.h(如果之前使用过Python),但这里我们不需要,为了避免错误,可以在SWIG命令中指定-DSWIGWORDSIZE64(如果系统是64位)或者根据情况整。但通常,如果只是C#,则不会包含Python.h,所以可以忽略。 - 编译项目,生成DLL(例如MathLibrary.dll)。注意,这个DLL将包含原始C++代码和包装代码。 步骤6:创建C#项目并添加生成的C#文件 -一个解决方案中,添加一个新的C#控制台应用程序项目(例如CSharpApp)。 -SWIG生成的C#文件(MathUtils.cs, MathUtilsPINVOKE.cs)添加到C#项目中。 -C#项目中,需要设置DLL的复制:将之前生成的MathLibrary.dll(在C++项目的输出目录中)复制到C#项目的输出目录(如bin\Debug\net5.0)中。可以通过设置“复制到输出目录”来实现,或者使用生成后事件。 步骤7:在C#C++代码 在C#项目的Main函数中,编写测试代码: ```csharp using System; namespace CSharpApp { class Program { static void Main(string[] args) { // 使用MathUtils类 MathUtils math = new MathUtils(); Console.WriteLine("3.5 + 2.1 = " + math.add(3.5, 2.1)); Console.WriteLine("5! = " + MathUtils.factorial(5)); } } } ``` 步骤8:配置依赖和生成顺序 - 在解决方案中,将C#项目设置为依赖于C++项目(这样每次生成解决方案时,会先编译C++项目,再编译C#项目)。 -C#项目中,添加对C++项目输出的引用(实际上是对DLL的引用,但这里不需要在引用中添加,因为DLL是动态加载的,只需要确保DLL在输出目录中)。 步骤9:运行 运行C#项目,应该可以看到输出结果。 注意事项: 1. 平台目标:确保C++C#项目的平台一致(例如都是x64或都是x86)。 2. 命名规范:C#中类名和命名空间遵循SWIG生成的文件(由模块名决定)。 3. 内存管理:如果C++类需要手动释放内存,在C#中应使用Dispose模式或using语句。 4. 异常处理:如果C++函数可能抛出异常,需要在SWIG接口文件中进行异常处理配置(如前所述)。 在VS2019中自动化: 可以配置自定义生成步骤,使得在每次编译C++项目前自动运行SWIG命令。方法如下: - 右键C++项目 -> 属性 -> 生成事件 -> 预生成事件。 - 在命令行中,输入SWIG命令,例如: ``` swig -c++ -csharp -outdir $(SolutionDir)CSharpApp\Generated math_utils.i ``` 这里假设将生成的C#文件放在C#项目的Generated文件夹中。 - 注意:需要确保swig.exe在PATH中,或者使用绝对路径。 引用: 以上步骤参考了SWIG官方文档[^1]和Visual Studio文档[^2]。 相关问题: 1. 在Visual Studio中如何配置SWIG的预生成事件? 2. 如何处理SWIG转换中C++类的析构函数和C#的垃圾回收? 3.C#中如何传递回函数给C++? 4. 如何将SWIG生成的C#代码封装成NuGet包?</think>### 在Visual Studio 2019中使用SWIGC++转换为C#的详细步骤 #### **1. 环境配置** 1. **安装SWIG** - 从[SWIG官网](http://www.swig.org/download.html)下载Windows版 - 解压到`C:\swigwin-4.1.1`(示例路径) - 添加环境变量:`PATH += C:\swigwin-4.1.1` - 验证安装:`swig -version`(应显示版本信息) 2. **VS2019工作负载** - 安装时勾选: - `.NET桌面开发` - `使用C++的桌面开发` - `.NET Core跨平台开发`(可选) #### **2. 创建C++ DLL项目** 1. **新建项目** `文件 → 新建 → 项目 → 动态链接库(DLL)` ```cpp // MathUtils.h #pragma once #ifdef MATHUTILS_EXPORTS #define MATHUTILS_API __declspec(dllexport) #else #define MATHUTILS_API __declspec(dllimport) #endif class MATHUTILS_API MathUtils { public: double Add(double a, double b); static int Factorial(int n); }; ``` ```cpp // MathUtils.cpp #include "pch.h" #include "MathUtils.h" double MathUtils::Add(double a, double b) { return a + b; } int MathUtils::Factorial(int n) { return (n <= 1) ? 1 : n * Factorial(n-1); } ``` 2. **配置项目属性** - 平台:`x64`(与C#项目一致) - `C/C++ → 高级 → 编译为C++代码 (/TP)` - `链接器 → 高级 → 目标文件扩展 → .dll` #### **3. 添加SWIG接口文件** 1. **创建`.i`文件** 右键项目 → 添加 → 新建项 → `math_utils.i` ```swig // math_utils.i %module MathUtils // C#命名空间 %{ #include "MathUtils.h" // 包含原始头文件 %} // 声明导出的类和方法 class MathUtils { public: MathUtils(); double Add(double a, double b); static int Factorial(int n); }; ``` 2. **配置自定义生成工具** - 右键`math_utils.i` → 属性 - 常规 → 项类型:`自定义生成工具` - 自定义生成工具 → 命令行: ``` swig -c++ -csharp -outdir $(ProjectDir)..\CSharpApp\Generated %(Identity) ``` - 输出:`math_utils_wrap.cxx` #### **4. 生成包装代码** 1. **编译C++项目** - 生成 → 生成解决方案 - 生成文件位置: - `math_utils_wrap.cxx`(添加到C++项目) - `MathUtils.cs`(在`../CSharpApp/Generated`目录) 2. **关键生成文件说明** | 文件 | 作用 | |------|------| | `MathUtils.cs` | C#代理类,包含包装方法 | | `MathUtilsPINVOKE.cs` | P/Invoke底层接口 | | `math_utils_wrap.cxx` | C++包装器源码 | #### **5. 创建C#控制台项目** 1. **添加生成文件** - 新建C#控制台项目(一解决方案) - 将生成的`MathUtils.cs`和`MathUtilsPINVOKE.cs`添加到项目 2. **配置DLL引用** ```csharp // Program.cs using System; using System.Runtime.InteropServices; namespace CSharpApp { class Program { [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern bool SetDllDirectory(string path); static void Main(string[] args) { // 设置DLL搜索路径 SetDllDirectory(@"..\x64\Debug\"); var math = new MathUtils(); Console.WriteLine($"3.5 + 2.1 = {math.Add(3.5, 2.1)}"); // 5.6 Console.WriteLine($"5! = {MathUtils.Factorial(5)}"); // 120 } } } ``` #### **6. 解决方案配置** 1. **项目依赖** - 右键解决方案 → 属性 → 项目依赖项 - 设置C#项目依赖C++项目 2. **生成后事件**(C++项目) ``` xcopy /Y "$(TargetPath)" "$(SolutionDir)CSharpApp\bin\$(Configuration)\net5.0\" xcopy /Y "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)CSharpApp\bin\$(Configuration)\net5.0\" ``` #### **7. 试技巧** 1. **混合模式试** - C#项目 → 属性 → - 启用本机代码试:`True` 2. **常见错误处理** | 错误 | 解决方案 | |------|----------| | `DllNotFoundException` | 检查DLL路径和平台一致性 | | `EntryPointNotFoundException` | 检查C++函数导出名(使用`dumpbin /exports MathUtils.dll`验证) | | 内存泄漏 | 在C#中显式用`Dispose()` | #### **8. 高级配置** 1. **处理STL容器** ```swig %include "std_vector.i" %template(IntVector) std::vector<int>; ``` 2. **回函数示例** ```swig // C++端 typedef void (*Callback)(int); void RegisterCallback(Callback func); ``` ```csharp // C#端 public delegate void CallbackDelegate(int value); [DllImport("MathUtils.dll")] public static extern void RegisterCallback(CallbackDelegate func); ``` > 参考:SWIG官方文档提供了完整的类型映射示例[^1] --- ### **可视化流程图** ```mermaid graph TD A[创建C++ DLL项目] --> B[添加SWIG接口文件.i] B --> C[配置自定义生成工具] C --> D[生成C#包装文件] D --> E[创建C#控制台项目] E --> F[添加包装文件到C#项目] F --> G[配置DLL引用和路径] G --> H[混合模式试] ```
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kagula086

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值