zoukankan      html  css  js  c++  java
  • 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-bw19-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 }

    还说那句话:种一棵树最好的时间是十年前,其次是现在。

  • 相关阅读:
    android入门之三【应用程序组成】
    Palm应用开发之一开发环境搭建
    android 入门之一【开发环境搭建】
    在DataGridView中的CheckBox值变更后立即获取值。
    根据字符串返回类型
    CSS模拟不同的拐角效果
    SQL查询生成交叉列表
    LinkButton 的 OnClick 事件 可以是一个方法
    代替marquee的滚动字幕效果代码
    JavaScript实现DataGrid中添加CheckBox列(全选与否)
  • 原文地址:https://www.cnblogs.com/jixin/p/4735105.html
Copyright © 2011-2022 走看看