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