zoukankan      html  css  js  c++  java
  • C#调用C++dll

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using System.Reflection.Emit;
    using System.Runtime.InteropServices;
    using System.Text;

    namespace TEDS_App
    {
    public enum ModePass
    {
    ByValue = 0x0001,
    ByRef = 0x0002
    }
    public class FaultFunc
    {
    [DllImport("kernel32.dll")]
    static extern IntPtr LoadLibrary(string lpFileName);
    [DllImport("kernel32.dll")]
    static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
    [DllImport("kernel32", EntryPoint = "FreeLibrary", SetLastError = true)]
    static extern bool FreeLibrary(IntPtr hModule);
    private IntPtr hModule = IntPtr.Zero;
    private IntPtr farProc = IntPtr.Zero;
    public void LoadDll(string lpFileName)
    {
    hModule = LoadLibrary(lpFileName);
    if (hModule == IntPtr.Zero)
    {
    throw (new Exception("没有找到:" + lpFileName + "."));
    }
    }
    public void LoadDll(IntPtr HMODULE)
    {
    if (HMODULE == IntPtr.Zero)
    {
    throw (new Exception("所传入的函数库模块的句柄为空"));
    }
    hModule = HMODULE;
    }
    public void LoadFun(string lpProcName)
    {
    if (hModule == IntPtr.Zero)
    {
    throw (new Exception("函数库模块的句柄为空,确保已进行加载dll操作"));
    }
    farProc = GetProcAddress(hModule, lpProcName);
    if (farProc == IntPtr.Zero)
    {
    throw (new Exception("没有找到:" + lpProcName + "这个函数的入口点"));
    }
    }
    public void LoadFun(string lpFileName, string lpProcName)
    {
    hModule = LoadLibrary(lpFileName);
    if (hModule == IntPtr.Zero)
    {
    throw (new Exception("没有找到:" + lpFileName + "."));
    }
    farProc = GetProcAddress(hModule, lpFileName);
    if (farProc == IntPtr.Zero)
    {
    throw (new Exception("没有找到:" + lpProcName + "这个函数的入口点"));
    }
    }
    public void UnLoadDll()
    {
    FreeLibrary(hModule);
    hModule = IntPtr.Zero;
    farProc = IntPtr.Zero;
    }
    public object Invoke(object[] ObjArray_Parameter, Type[] TypeArray_parameterType, ModePass[] ModePassArray_Parameter, Type Type_Return)
    {
    if (hModule == IntPtr.Zero)
    throw (new Exception("函数库模块的句柄为空,请确保进行了LoadLll操作"));
    if (farProc == IntPtr.Zero)
    throw (new Exception("函数指针为空,请确保已进行LoadFun操作"));
    if (ObjArray_Parameter.Length != ModePassArray_Parameter.Length)
    throw (new Exception("参数个数及其传递方式的个数不匹配"));
    AssemblyName MyAssemblyName = new AssemblyName();
    MyAssemblyName.Name = "InvokeFun";
    AssemblyBuilder MyAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(MyAssemblyName, AssemblyBuilderAccess.Run);
    ModuleBuilder MyModuleBuilder = MyAssemblyBuilder.DefineDynamicModule("InvokeDll");
    MethodBuilder MyMethodBuilder = MyModuleBuilder.DefineGlobalMethod("FaultFun", MethodAttributes.Public | MethodAttributes.Static, Type_Return, TypeArray_parameterType);
    ILGenerator IL = MyMethodBuilder.GetILGenerator();
    int i;
    for (i = 0; i < ObjArray_Parameter.Length; i++)
    {
    switch (ModePassArray_Parameter[i])
    {
    case ModePass.ByValue:
    IL.Emit(OpCodes.Ldarg, i);
    break;
    case ModePass.ByRef:
    IL.Emit(OpCodes.Ldarga, i);
    break;
    default:
    throw (new Exception("第" + (i + 1).ToString() + "个参数没有给定正确的传递方式"));
    }
    }
    if (IntPtr.Size == 4)
    {
    IL.Emit(OpCodes.Ldc_I4, farProc.ToInt32());
    }
    else if (IntPtr.Size == 8)
    {
    IL.Emit(OpCodes.Ldc_I8, farProc.ToInt64());
    }
    else
    {
    throw new PlatformNotSupportedException();
    }
    IL.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, Type_Return, TypeArray_parameterType);
    IL.Emit(OpCodes.Ret);
    MyModuleBuilder.CreateGlobalFunctions();
    MethodInfo MyMethodInfo = MyModuleBuilder.GetMethod("FaultFun");
    return MyMethodInfo.Invoke(null, ObjArray_Parameter);
    }
    public object Invoke(IntPtr IntPtr_Function, object[] ObjArray_Parameter, Type[] TypeArray_ParameterType, ModePass[] ModePassArray_Parameter, Type Type_Return)
    {
    if (hModule == IntPtr.Zero)
    throw (new Exception("函数库模块的句柄为空,请确保已进行LoadDll操作"));
    if (IntPtr_Function == IntPtr.Zero)
    throw (new Exception("函数指针IntPtr_Function为空"));
    farProc = IntPtr_Function;
    return Invoke(ObjArray_Parameter, TypeArray_ParameterType, ModePassArray_Parameter, Type_Return);
    }
    }

    }

    调用方式如下:

    PlusFunction.LoadDll(@"C:win32dll.dll");//PlusFunction为调用类的实例
    PlusFunction.LoadFun("MyFun");
    byte[] a = File.ReadAllBytes(@"E:19-bw19-73.jpg");
    object[] Parameters = new object[] {a}; // 实参为a
    Type[] ParameterTypes = new Type[] { typeof(byte[])}; // 实参类型为byte[]
    ModePass[] themode = new ModePass[] {ModePass.ByValue}; // 传送方式为值传
    Type Type_Return = typeof(int); // 返回类型为int
    ret = (int)PlusFunction.Invoke(Parameters, ParameterTypes, themode, Type_Return);

    其实,c++与c#主要的就是数据类型的对应了。简单点的还好说,稍微复杂的各种麻烦。。。关键是不好调试。

    c++ c#
    char* char[](string.tochararray)
    byte* byte[]
    int int
    int* int[]
    结构体
    c++
    typedef struct SRectChange_TAG
    {
    //NV_RECT rect;
    int x;//左上角x轴坐标
    int y;//左上角y轴坐标
    int width;//宽
    int height;//高
    int degree;//报错级别;1最低,目前暂时设定3级
    }
    SRectChange;
    c#
    [StructLayout(LayoutKind.Sequential)]
    public struct SRectChange
    {
    public int x;
    public int y;
    public int width;
    public int height;
    public int degree;
    }
    结构体传递
    [DllImport("win32dll.dll", EntryPoint = "MyFun", CallingConvention = CallingConvention.Cdecl)]
    public static extern int MyFun(ref SRectChange rect, char[] str, char[] str2);
    c++结构体
    typedef struct
    {
    int osVersion;
    int majorVersion;
    int minorVersion;
    int buildNum;
    int platFormId;
    char szVersion[128];
    }OSINFO;
    c#
    // OSINFO定义
    [StructLayout(LayoutKind.Sequential)]
    public struct OSINFO
    {
    public int osVersion;
    public int majorVersion;
    public int minorVersion;
    public int buildNum;
    public int platFormId;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string szVersion;
    }

    结构体数组传递
    c#代码
    [DllImport("win32dll.dll", EntryPoint = "MyFun", CallingConvention = CallingConvention.Cdecl)]
    public static extern int MyFun(IntPtr p, char[] str, char[] str2);
    数组传指针
    char[] newpic = ("123123123123").ToCharArray();
    char[] oldpic = ("231231234123").ToCharArray();
    SRectChange[] rects = new SRectChange[5];
    for (int i = 0; i < rects.Length; i++)
    {
    rects[i] = new SRectChange();
    }
    IntPtr[] ptArr = new IntPtr[1];
    ptArr[0] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SRectChange)) * 5); //分配包含两个元素的数组
    IntPtr pt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SRectChange)));
    Marshal.Copy(ptArr, 0, pt, 1); //拷贝指针数组
    MyFun(pt, newpic, oldpic);
    for (int i = 0; i < 5; i++)
    {
    rects[i] = (SRectChange)Marshal.PtrToStructure((IntPtr)(pt.ToInt32() + i * Marshal.SizeOf(typeof(SRectChange))), typeof(SRectChange));
    Console.WriteLine("x:{0} y:{1}", rects[i].x, rects[i].y);
    }

  • 相关阅读:
    [ solr入门 ] 在schema.xml中加入自己的分词工具
    SQLServer2005获取大数据集时内存不足的解决办法[转]
    java位操作基本教程[转]
    log4j的最佳实践(转)
    [ lucene扩展 ] "Did you mean" feature with Apache Lucene SpellChecker
    java image filters[02]过滤器初探
    PHP serialize 和 JSON 解析与区别
    js 实现 静态缓存页面中访问动态IP下载地址
    smarty section foreach遍历多维数组
    【转】window.open 参数
  • 原文地址:https://www.cnblogs.com/niuniu0108/p/7873876.html
Copyright © 2011-2022 走看看