项目要用到C#调用C++代码,折腾了好久,终于搞定了。总结一下。

问题的复杂性在于C++是非托管代码(unmanaged/native code),C#是托管代码(managed code),不可直接调用。这里先讲一下C#调用C++中的函数。这个相对简单一些,网上现成的代码也比较多,这里的就是转自http://tech.ddvip.com/2009-03/1236764166111066_1.html的方法。

有两种方法:静态调用和动态调用。

静态调用

假设有C++代码nativeCPP.cpp:

1 extern "C" __declspec(dllexport) int add(int x, int y)
2 {
3  return x + y;
4 }
5  

 编译生成nativeCPP.dll,将其放在C#工程的bin目录下。C#代码如下:

1 using System;
2  using System.Collections.Generic;
3  using System.Text;
4 using System.Runtime.InteropServices; //一定要有
5
6 namespace InteropDemo
7 {
8     class Program
9     {
10         [DllImport("nativeCPP.dll", EntryPoint = "add", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
11         public static extern int add(int a, int b); //正常声明即可
12         static void Main(string[] args)
13         {
14             Console.WriteLine(add(12));
15             Console.Read();
16          }
17     }
18 }
19
动态调用

1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Runtime.InteropServices;
5
6 namespace InteropDemo
7 {
8 //封装kernel32中的几个方法(虽然我觉得没什么必要)
9     public static class NativeMethod
10     {
11         [DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
12         public static extern int LoadLibrary(
13             [MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);
14
15         [DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
16         public static extern IntPtr GetProcAddress(int hModule,
17             [MarshalAs(UnmanagedType.LPStr)] string lpProcName);
18
19         [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
20         public static extern bool FreeLibrary(int hModule);
21     }
22 class Program
23     {
24         static void Main(string[] args)
25         {
26             //1. 动态加载C++ Dll
27             int hModule = NativeMethod.LoadLibrary(@"c:nativeCPP.dll");
28             if (hModule == 0) return;
29
30             //2. 读取函数指针
31             IntPtr intPtr = NativeMethod.GetProcAddress(hModule, "Add");
32
33             //3. 将函数指针封装成委托
34             Add addFunction = (Add)Marshal.GetDelegateForFunctionPointer(intPtr, typeof(Add));
35
36             //4. 测试
37             Console.WriteLine(addFunction(1, 2));
38             Console.Read();
39         }
40
41         /// <summary>
42         /// 函数指针
43         /// </summary>
44         /// <param name="a"></param>
45         /// <param name="b"></param>
46         /// <returns></returns>
47         delegate int Add(int a, int b);
48
49     }
50
51 }
我不懂动态调用与静态调用的原理,只知道从表相来看,静态调用C++的dll必须放在C#工程目录bin下,而动态的话只要在C#中指定路径即可。
Posted on 2011-01-29 20:12  cdbean  阅读(5836)  评论(1编辑  收藏  举报