C#与C++互调教程:静态与动态链接示例

2星 需积分: 42 9 下载量 23 浏览量 更新于2024-09-14 1 收藏 18KB DOCX 举报
"该文档详细介绍了如何在C#托管代码中调用C++非托管代码,包括静态调用和动态调用两种方式。" 在软件开发中,有时我们需要在使用现代高级语言如C#(托管代码)的项目中,调用用C++编写的老代码或者利用已有的库(非托管代码)。本文档提供了具体的步骤和实例,帮助开发者实现这种跨语言的互操作性。 一、C#中静态调用C++动态链接 1. 首先,创建一个C++项目(命名为CppDemo),选择Win32 Console Application,并选择DLL模板来创建动态链接库。 2. 在生成的DllDemo.cpp文件中,定义一个需要导出的C++函数。这里是一个简单的加法函数,使用`extern "C"`避免名称修饰,`__declspec(dllexport)`用于导出函数: ```cpp extern "C" __declspec(dllexport) int Add(int a, int b) { return a + b; } ``` 3. 编译C++项目,生成CppDemo.dll。 4. 创建一个新的C#控制台应用项目(InteropDemo),并添加对`System.Runtime.InteropServices`命名空间的引用。 5. 在C#项目的Program.cs文件中,使用`[DllImport]`特性声明C++的Add函数,指定dll名称、入口点以及调用约定: ```csharp using System; using System.Runtime.InteropServices; namespace InteropDemo { class Program { [DllImport("CppDemo.dll", EntryPoint = "Add", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)] public static extern int Add(int a, int b); static void Main(string[] args) { Console.WriteLine(Add(1, 2)); Console.ReadKey(); } } } ``` 6. 运行C#项目,确保CppDemo.dll位于C#项目的输出目录下,以便C#能正确加载并调用C++函数。 二、C#中动态调用C++动态链接 静态调用虽然简单,但存在依赖DLL路径的问题。为了解决这个问题,可以采用动态加载C++ DLL的方式。在C#中,可以使用`DllImportAttribute`的`SetDllImportData`方法来动态加载和调用非托管代码: 1. 首先,需要引入`System.Reflection.Emit`命名空间,用于动态生成委托类型。 2. 在C#代码中,先加载动态链接库(通过`LoadLibrary`),获取函数地址(`GetProcAddress`),然后根据函数签名创建对应的委托类型,并设置到`DllImportAttribute`。 3. 使用`Marshal.GetFunctionPointerForDelegate`获取委托的函数指针,并调用函数。 这种方式更灵活,但需要处理更多的细节,如错误处理、内存管理等。动态加载适用于那些在运行时才知道具体依赖的库或函数的情况,比如在策略模式、工厂模式等设计模式中。 总结,通过C#的`DllImport`特性和`Reflection.Emit`,我们可以实现C#托管代码与C++非托管代码之间的有效交互。无论是静态还是动态调用,都需要关注内存管理、异常处理和平台调用约定的匹配,以确保程序的稳定性和正确性。这种跨语言的互操作性是.NET框架提供的一项强大功能,使得开发者能够充分利用现有的C++资源,同时享受C#等现代语言带来的开发便利。