现在项目基本都是旁边C++的哥们做好dll扔给我,然后我调用。好久之前晚上down了一份c#调用c++dll的方法,出处早已经遗忘。闲来无事,放上来好了。原作者看到后可以留言,我会把您链接放上的,帮了我很多!!!
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Reflection;
5 using System.Reflection.Emit;
6 using System.Runtime.InteropServices;
7 using System.Text;
8
9 namespace TEDS_App
10 {
11 public enum ModePass
12 {
13 ByValue = 0x0001,
14 ByRef = 0x0002
15 }
16 public class FaultFunc
17 {
18 [DllImport("kernel32.dll")]
19 static extern IntPtr LoadLibrary(string lpFileName);
20 [DllImport("kernel32.dll")]
21 static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
22 [DllImport("kernel32", EntryPoint = "FreeLibrary", SetLastError = true)]
23 static extern bool FreeLibrary(IntPtr hModule);
24 private IntPtr hModule = IntPtr.Zero;
25 private IntPtr farProc = IntPtr.Zero;
26 public void LoadDll(string lpFileName)
27 {
28 hModule = LoadLibrary(lpFileName);
29 if (hModule == IntPtr.Zero)
30 {
31 throw (new Exception("没有找到:" + lpFileName + "."));
32 }
33 }
34 public void LoadDll(IntPtr HMODULE)
35 {
36 if (HMODULE == IntPtr.Zero)
37 {
38 throw (new Exception("所传入的函数库模块的句柄为空"));
39 }
40 hModule = HMODULE;
41 }
42 public void LoadFun(string lpProcName)
43 {
44 if (hModule == IntPtr.Zero)
45 {
46 throw (new Exception("函数库模块的句柄为空,确保已进行加载dll操作"));
47 }
48 farProc = GetProcAddress(hModule, lpProcName);
49 if (farProc == IntPtr.Zero)
50 {
51 throw (new Exception("没有找到:" + lpProcName + "这个函数的入口点"));
52 }
53 }
54 public void LoadFun(string lpFileName, string lpProcName)
55 {
56 hModule = LoadLibrary(lpFileName);
57 if (hModule == IntPtr.Zero)
58 {
59 throw (new Exception("没有找到:" + lpFileName + "."));
60 }
61 farProc = GetProcAddress(hModule, lpFileName);
62 if (farProc == IntPtr.Zero)
63 {
64 throw (new Exception("没有找到:" + lpProcName + "这个函数的入口点"));
65 }
66 }
67 public void UnLoadDll()
68 {
69 FreeLibrary(hModule);
70 hModule = IntPtr.Zero;
71 farProc = IntPtr.Zero;
72 }
73 public object Invoke(object[] ObjArray_Parameter, Type[] TypeArray_parameterType, ModePass[] ModePassArray_Parameter, Type Type_Return)
74 {
75 if (hModule == IntPtr.Zero)
76 throw (new Exception("函数库模块的句柄为空,请确保进行了LoadLll操作"));
77 if (farProc == IntPtr.Zero)
78 throw (new Exception("函数指针为空,请确保已进行LoadFun操作"));
79 if (ObjArray_Parameter.Length != ModePassArray_Parameter.Length)
80 throw (new Exception("参数个数及其传递方式的个数不匹配"));
81 AssemblyName MyAssemblyName = new AssemblyName();
82 MyAssemblyName.Name = "InvokeFun";
83 AssemblyBuilder MyAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(MyAssemblyName, AssemblyBuilderAccess.Run);
84 ModuleBuilder MyModuleBuilder = MyAssemblyBuilder.DefineDynamicModule("InvokeDll");
85 MethodBuilder MyMethodBuilder = MyModuleBuilder.DefineGlobalMethod("FaultFun", MethodAttributes.Public | MethodAttributes.Static, Type_Return, TypeArray_parameterType);
86 ILGenerator IL = MyMethodBuilder.GetILGenerator();
87 int i;
88 for (i = 0; i < ObjArray_Parameter.Length; i++)
89 {
90 switch (ModePassArray_Parameter[i])
91 {
92 case ModePass.ByValue:
93 IL.Emit(OpCodes.Ldarg, i);
94 break;
95 case ModePass.ByRef:
96 IL.Emit(OpCodes.Ldarga, i);
97 break;
98 default:
99 throw (new Exception("第" + (i + 1).ToString() + "个参数没有给定正确的传递方式"));
100 }
101 }
102 if (IntPtr.Size == 4)
103 {
104 IL.Emit(OpCodes.Ldc_I4, farProc.ToInt32());
105 }
106 else if (IntPtr.Size == 8)
107 {
108 IL.Emit(OpCodes.Ldc_I8, farProc.ToInt64());
109 }
110 else
111 {
112 throw new PlatformNotSupportedException();
113 }
114 IL.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, Type_Return, TypeArray_parameterType);
115 IL.Emit(OpCodes.Ret);
116 MyModuleBuilder.CreateGlobalFunctions();
117 MethodInfo MyMethodInfo = MyModuleBuilder.GetMethod("FaultFun");
118 return MyMethodInfo.Invoke(null, ObjArray_Parameter);
119 }
120 public object Invoke(IntPtr IntPtr_Function, object[] ObjArray_Parameter, Type[] TypeArray_ParameterType, ModePass[] ModePassArray_Parameter, Type Type_Return)
121 {
122 if (hModule == IntPtr.Zero)
123 throw (new Exception("函数库模块的句柄为空,请确保已进行LoadDll操作"));
124 if (IntPtr_Function == IntPtr.Zero)
125 throw (new Exception("函数指针IntPtr_Function为空"));
126 farProc = IntPtr_Function;
127 return Invoke(ObjArray_Parameter, TypeArray_ParameterType, ModePassArray_Parameter, Type_Return);
128 }
129 }
130
131 }
一直以来,对于C++程序员报以崇高的敬意。。。一直觉得他们屌屌的,哈哈。
调用方式如下:
1 PlusFunction.LoadDll(@"C:\win32dll.dll");//PlusFunction为调用类的实例
2 PlusFunction.LoadFun("MyFun");
3 byte[] a = File.ReadAllBytes(@"E:\19-bw\19-73.jpg");
4 object[] Parameters = new object[] {a}; // 实参为a
5 Type[] ParameterTypes = new Type[] { typeof(byte[])}; // 实参类型为byte[]
6 ModePass[] themode = new ModePass[] {ModePass.ByValue}; // 传送方式为值传
7 Type Type_Return = typeof(int); // 返回类型为int
8 ret = (int)PlusFunction.Invoke(Parameters, ParameterTypes, themode, Type_Return);
其实,c++与c#主要的就是数据类型的对应了。简单点的还好说,稍微复杂的各种麻烦。。。关键是不好调试。
下面举些我用到的例子,以后遇到其他的再补充。日积月累- -
1 c++ c#
2 char* char[](string.tochararray)
3 byte* byte[]
4 int int
5 int* int[]
6 结构体
7 c++
8 typedef struct SRectChange_TAG
9 {
10 //NV_RECT rect;
11 int x;//左上角x轴坐标
12 int y;//左上角y轴坐标
13 int width;//宽
14 int height;//高
15 int degree;//报错级别;1最低,目前暂时设定3级
16 }
17 SRectChange;
18 c#
19 [StructLayout(LayoutKind.Sequential)]
20 public struct SRectChange
21 {
22 public int x;
23 public int y;
24 public int width;
25 public int height;
26 public int degree;
27 }
28 结构体传递
29 [DllImport("win32dll.dll", EntryPoint = "MyFun", CallingConvention = CallingConvention.Cdecl)]
30 public static extern int MyFun(ref SRectChange rect, char[] str, char[] str2);
31 c++结构体
32 typedef struct
33 {
34 int osVersion;
35 int majorVersion;
36 int minorVersion;
37 int buildNum;
38 int platFormId;
39 char szVersion[128];
40 }OSINFO;
41 c#
42 // OSINFO定义
43 [StructLayout(LayoutKind.Sequential)]
44 public struct OSINFO
45 {
46 public int osVersion;
47 public int majorVersion;
48 public int minorVersion;
49 public int buildNum;
50 public int platFormId;
51 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
52 public string szVersion;
53 }
54
55 结构体数组传递
56 c#代码
57 [DllImport("win32dll.dll", EntryPoint = "MyFun", CallingConvention = CallingConvention.Cdecl)]
58 public static extern int MyFun(IntPtr p, char[] str, char[] str2);
59 数组传指针
60 char[] newpic = ("123123123123").ToCharArray();
61 char[] oldpic = ("231231234123").ToCharArray();
62 SRectChange[] rects = new SRectChange[5];
63 for (int i = 0; i < rects.Length; i++)
64 {
65 rects[i] = new SRectChange();
66 }
67 IntPtr[] ptArr = new IntPtr[1];
68 ptArr[0] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SRectChange)) * 5); //分配包含两个元素的数组
69 IntPtr pt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SRectChange)));
70 Marshal.Copy(ptArr, 0, pt, 1); //拷贝指针数组
71 MyFun(pt, newpic, oldpic);
72 for (int i = 0; i < 5; i++)
73 {
74 rects[i] = (SRectChange)Marshal.PtrToStructure((IntPtr)(pt.ToInt32() + i * Marshal.SizeOf(typeof(SRectChange))), typeof(SRectChange));
75 Console.WriteLine("x:{0} y:{1}", rects[i].x, rects[i].y);
76 }
还说那句话:种一棵树最好的时间是十年前,其次是现在。