C#调用C++ DLL教程:实例解析与参数传递

需积分: 20 5 下载量 175 浏览量 更新于2024-09-09 收藏 18KB DOCX 举报
"这篇文章主要介绍了如何在C#代码中调用C或C++编译的DLL,包括如何处理输入输出字符串、结构体参数以及回调函数的调用方法。" 在C#编程中,有时我们需要利用已有的C或C++编写的DLL库,这时就需要了解如何在托管的C#环境中调用非托管的DLL。本教程将详细讲解这个过程,并通过具体的代码示例来演示。 首先,C++ DLL的部分代码展示了几个导出函数,这些函数包括: 1. `Test` 函数:一个简单的返回整数值的函数,无参数。 2. `TCharPara` 函数:接受一个输入字符串指针和长度,以及一个输出字符串指针,将输入字符串复制到输出字符串。 3. `TStructPara` 函数:接收一个结构体指针,修改结构体成员的值。 4. `TCallback` 函数:接受一个回调函数指针和一个输出字符串指针,通过回调函数处理输出字符串。 为了在C#中调用这些函数,我们需要使用`DllImport`属性来声明对应的函数,并使用`UnmanagedType`来指定参数类型。以下是C#代码示例: ```csharp using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; namespace TCallCDll { // 定义结构体XY,与C++中的结构体匹配 [StructLayout(LayoutKind.Sequential)] public struct XY { public int x; public int y; } // DllImport声明,指定DLL名称和函数原型 [DllImport("dll.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int Test(); [DllImport("dll.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int TCharPara([MarshalAs(UnmanagedType.LPStr)] string inStr, int len, [MarshalAs(UnmanagedType.LPStr)] out string outStr); [DllImport("dll.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int TStructPara(ref XY xy); [DllImport("dll.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int TCallback(IntPtr pf, [MarshalAs(UnmanagedType.LPStr)] out string outStr); } ``` 这里,`DllImport`特性用于导入DLL,`CallingConvention`指定了调用约定,`MarshalAs`用于指定参数的.NET等效类型。 使用以上声明,就可以在C#中调用DLL中的函数了。例如,调用`Test`函数: ```csharp int result = TCallCDll.Test(); Console.WriteLine("Test function returned: " + result); ``` 对于`TCharPara`,你需要提供输入字符串和输出字符串的缓冲区: ```csharp string input = "Hello"; int len = input.Length + 1; StringBuilder output = new StringBuilder(len); int ret = TCallCDll.TCharPara(input, len, out output); Console.WriteLine("Output string: " + output.ToString()); ``` 对于结构体参数,如`TStructPara`,可以创建结构体实例并传递引用: ```csharp XY xy = new XY { x = 0, y = 0 }; TCallCDll.TStructPara(ref xy); Console.WriteLine($"After TStructPara: x={xy.x}, y={xy.y}"); ``` 对于回调函数`TCallback`,你需要定义一个C#中的委托类型,并传递该类型的实例作为参数: ```csharp delegate void CallbackDelegate(string str); CallbackDelegate myCallback = new CallbackDelegate(PrintString); [DllImport("dll.dll", CallingConvention = CallingConvention.Cdecl)] private static extern int TCallback(IntPtr callback, [MarshalAs(UnmanagedType.LPStr)] out string outStr); public static void PrintString(string str) { Console.WriteLine("Callback called with: " + str); } string output; int ret = TCallback(Marshal.GetFunctionPointerForDelegate(myCallback), out output); ``` 通过这种方式,C#程序就能成功调用C或C++编写的DLL,并处理各种类型的数据。需要注意的是,在实际应用中,可能还需要处理错误检查、异常处理以及内存管理等问题,确保跨语言调用的稳定性和安全性。