现在项目基本都是旁边C++的哥们做好dll扔给我,然后我调用。好久之前晚上down了一份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 = ; 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 + ).ToString() + "个参数没有给定正确的传递方式"));
}
}
if (IntPtr.Size == )
{
IL.Emit(OpCodes.Ldc_I4, farProc.ToInt32());
}
else if (IntPtr.Size == )
{
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);
}
} }

一直以来,对于C++程序员报以崇高的敬意。。。一直觉得他们屌屌的,哈哈。

调用方式如下:

 PlusFunction.LoadDll(@"C:\win32dll.dll");//PlusFunction为调用类的实例
PlusFunction.LoadFun("MyFun");
byte[] a = File.ReadAllBytes(@"E:\19-bw\19-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[];
}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 = )]
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 = ("").ToCharArray();
char[] oldpic = ("").ToCharArray();
SRectChange[] rects = new SRectChange[];
for (int i = ; i < rects.Length; i++)
{
rects[i] = new SRectChange();
}
IntPtr[] ptArr = new IntPtr[];
ptArr[] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SRectChange)) * ); //分配包含两个元素的数组
IntPtr pt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SRectChange)));
Marshal.Copy(ptArr, , pt, ); //拷贝指针数组
MyFun(pt, newpic, oldpic);
for (int i = ; i < ; 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);
}

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

C#调用C++ Dll的更多相关文章

  1. c# 调用c++DLL方法及注意事项

    引用命名空间 using System.Runtime.InteropServices 调用方法: 一.静态加载 用DllImprot方式来加载c++DLL.如下格式: //对应c++方法 //voi ...

  2. 在.net中调用Delphi dll的Pchar转换

    Pchar是非托管代码,要在.net中调用Delphi dll中的功能,请使用MarshalAs属性告知.net调用PInvoke去转换.net中标准的string类型.如果Delphi dll是De ...

  3. Java调用第三方dll文件的使用方法 System.load()或System.loadLibrary()

    Java调用第三方dll文件的使用方法 public class OtherAdapter { static { //System.loadLibrary("Connector") ...

  4. C#调用C++ DLL类方法

    C++的优势在于高效灵活,C#的优势在于简单易用,两者结合起来对项目开发来说是件好事,而且C++不容易反编译,也保障了代码的安全性,如果一些核心算法使用C#编写,那么保密就是一个问题. C++生成的D ...

  5. paip.java 调用c++ dll so总结

    paip.java 调用c++ dll so总结 ///////JNA (这个ms sun 的) 我目前正做着一个相关的项目,说白了JNA就是JNI的替代品,以前用JNI需要编译一层中间库,现在JNA ...

  6. C#调用C++ DLL 文件

    说来惭愧,都注册一年多了,却没有发表过一篇正式的博文,中间很多学习的过程也没有记录下来.如今到了一个新的环境,也有了学习的机会,一定要把每天的收获记录一下. 要做的东西需要引用C++编写的DLL,刚开 ...

  7. LR调用动态链接库DLL

    什么是动态库? 动态库一般又叫动态链接库(DLL),是Dynamic Link Library 的缩写形式,DLL是一个包含可由多个程序同时使用的代码和数据的库. 动态链接提供了一种方法 ,使进程可以 ...

  8. 【JNI】OPUS压缩与解压的JNI调用(.DLL版本)

    OPUS压缩与解压的JNI调用(.DLL版本) 一.写在开头: 理论上讲,这是我在博客园的第一篇原创的博客,之前也一直想找个地方写点东西,把最近做的一些东西归纳总结下,但是一般工程做完了一高兴就把东西 ...

  9. c#调用c++ dll的几种类型(转)

    http://www.sosuo8.com/article-2012/dllleixingzhuanhuan.htm   在合作开发时,C#时常需要调用C++DLL,当传递参数时时常遇到问题,尤其是传 ...

随机推荐

  1. SQL Server int类型值最大2147483647(2^31 - 1)

    突发奇想,一个字增字段,假设每天增加1000条记录,多少年之后写不进int类型的字段了2147483647 / 1000 / 365 = 5883.51684109589041095890410958 ...

  2. Battery-historian 参数说明

    部分参数说明 battery_level 电量,可以看出电量的变化.比如上图中的数据显示刚开始电量是100%,然后在第11秒-12秒中间的某个时刻降到了99%. plugged 充电状态,这一栏显示是 ...

  3. C/C++程序员面试易错题

    c部分::::::::::::::::::::::::::::::::::: . 关键字volatile有什么含意? 并给出三个不同的例 子. [参考答案]一个定义为volatile的变量是说这变量可 ...

  4. socket学习笔记——select函数的使用(windows)

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <winsock2.h ...

  5. 洛谷P2735 电网 Electric Fences

    P2735 电网 Electric Fences 11通过 28提交 题目提供者该用户不存在 标签USACO 难度普及/提高- 提交  讨论  题解 最新讨论 暂时没有讨论 题目描述 在本题中,格点是 ...

  6. 华为OJ平台——统计字符串中的大写字母

    题目描述: 统计字符串中的大写字母的个数 输入: 一行字符串 输出: 字符串中大写字母的个数(当空串时输出0) 思路: 这一题很简单,直接判断字符串中的每一个字符即可,唯一要注意的一点是输入的字符串可 ...

  7. JS &#8203; ZERO WIDTH SPACE

    如上编码 ZERO WIDTH SPACE  在各个语言的表达. JS中使用 var b = a.replace(/\u200B/g,''); 来替换,去掉 ZERO WIDTH SPACE . ht ...

  8. PAT1030. Travel Plan

    //晴神模板,dij+dfs,貌似最近几年PAT的的图论大体都这么干的,现在还在套用摸板阶段....估计把这及格图论题题搞完,dij,dfs,并查集就掌握差不多了(模板还差不多)为何bfs能自己干出来 ...

  9. grep使用

    grep常用的使用方法 grep –rns “match_content”filename 查看匹配内容的行 find /path –name “*.h” –o –name “*.cpp” | xar ...

  10. asp.net ashx 一般处理程序 使用async await异步直接 copy可用哦

    以前一直很懒  碰到ashx要用await异步就绕开  用aspx  或者mvc异步控制器  这次公司需要  我查了国内的文章基本都不能简单copy来处理一堆错关键的过程中函数BeginProcess ...