現在項目基本都是旁邊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 }
還說那句話:種一棵樹最好的時間是十年前,其次是現在。