程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#調用C++ Dll,

C#調用C++ Dll,

編輯:C#入門知識

C#調用C++ Dll,


現在項目基本都是旁邊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 }

還說那句話:種一棵樹最好的時間是十年前,其次是現在。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved