using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; //1. 打开项目“Tzb”,打开类视图,右击“Tzb”,选择“添加”-->“类”,类名设置为“dld”,
//即dynamic loading dll 的每个单词的开头字母。
//2. 添加所需的命名空间及声明参数传递方式枚举:
using System.Runtime.InteropServices; // 用 DllImport 需用此 命名空间
using System.Reflection; // 使用 Assembly 类需用此 命名空间
using System.Reflection.Emit; // 使用 ILGenerator 需用此 命名空间 namespace WpfApplication1
{
//在“public class dld”上面添加如下代码声明参数传递方式枚举:
///
/// 参数传递方式枚举 ,ByValue 表示值传递 ,ByRef 表示址传递
/// public enum ModePass
{
ByValue = 0x0001,
ByRef = 0x0002
}
public class DLD
{ //3. 声明LoadLibrary、GetProcAddress、FreeLibrary及私有变量hModule和farProc:
///
/// 原型是 :HMODULE LoadLibrary(LPCTSTR lpFileName);
///
/// < param name="lpFileName" / >DLL 文件名
/// 函数库模块的句柄
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName); ///
/// 原型是 : FARPROC GetProcAddress(HMODULE hModule, LPCWSTR lpProcName);
///
/// < param name="hModule" / > 包含需调用函数的函数库模块的句柄
/// < param name="lpProcName" / > 调用函数的名称
/// 函数指针 [DllImport("kernel32.dll")]
static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); ///
/// 原型是 : BOOL FreeLibrary(HMODULE hModule);
///
/// < param name="hModule" / > 需释放的函数库模块的句柄
/// 是否已释放指定的 Dll [DllImport("kernel32", EntryPoint = "FreeLibrary", SetLastError = true)]
static extern bool FreeLibrary(IntPtr hModule); ///
/// Loadlibrary 返回的函数库模块的句柄
/// private IntPtr hModule = IntPtr.Zero; ///
/// GetProcAddress 返回的函数指针
/// public IntPtr farProc = IntPtr.Zero; //4. 添加LoadDll方法,并为了调用时方便,重载了这个方法:
///
/// 装载 Dll
///
/// < param name="lpFileName" / >DLL 文件名 public void LoadDll(string lpFileName)
{ hModule = LoadLibrary(lpFileName);
if (hModule == IntPtr.Zero)
throw (new Exception(" 没有找到 :" + lpFileName + "."));
} // 若已有已装载Dll的句柄,可以使用LoadDll方法的第二个版本:
public void LoadDll(IntPtr HMODULE)
{
if (HMODULE == IntPtr.Zero)
throw (new Exception(" 所传入的函数库模块的句柄 HMODULE 为空 ."));
hModule = HMODULE;
} //5. 添加LoadFun方法,并为了调用时方便,也重载了这个方法,方法的具体代码及注释如下:
///
/// 获得函数指针
///
/// < param name="lpProcName" / > 调用函数的名称 public void LoadFun(string lpProcName)
{ // 若函数库模块的句柄为空,则抛出异常 if (hModule == IntPtr.Zero)
throw (new Exception(" 函数库模块的句柄为空 , 请确保已进行 LoadDll 操作 !"));
// 取得函数指针
farProc = GetProcAddress(hModule, lpProcName); // 若函数指针,则抛出异常
if (farProc == IntPtr.Zero)
throw (new Exception(" 没有找到 : " + lpProcName + " 这个函数的入口点 ")); } ///
/// 获得函数指针
///
/// < param name="lpFileName" / > 包含需调用函数的 DLL 文件名
/// < param name="lpProcName" / > 调用函数的名称 public void LoadFun(string lpFileName, string lpProcName)
{ // 取得函数库模块的句柄
hModule = LoadLibrary(lpFileName); // 若函数库模块的句柄为空,则抛出异常
if (hModule == IntPtr.Zero)
throw (new Exception(" 没有找到 :" + lpFileName + ".")); // 取得函数指针
farProc = GetProcAddress(hModule, lpProcName); // 若函数指针,则抛出异常
if (farProc == IntPtr.Zero)
throw (new Exception(" 没有找到 :" + lpProcName + " 这个函数的入口点 ")); } //6. 添加UnLoadDll及Invoke方法,Invoke方法也进行了重载:
///
/// 卸载 Dll
/// public void UnLoadDll()
{
FreeLibrary(hModule);
hModule = IntPtr.Zero;
farProc = IntPtr.Zero;
} ///
/// 调用所设定的函数
///
/// < param name="ObjArray_Parameter" / > 实参
/// < param name="TypeArray_ParameterType" / > 实参类型
/// < param name="ModePassArray_Parameter" / > 实参传送方式
/// < param name="Type_Return" / > 返回类型
/// 返回所调用函数的 object public object Invoke(object[] ObjArray_Parameter, Type[] TypeArray_ParameterType,
ModePass[] ModePassArray_Parameter, Type Type_Return)
{ // 下面 3 个 if 是进行安全检查 , 若不能通过 , 则抛出异常
if (hModule == IntPtr.Zero)
throw (new Exception(" 函数库模块的句柄为空 , 请确保已进行 LoadDll 操作 !"));
if (farProc == IntPtr.Zero)
throw (new Exception(" 函数指针为空 , 请确保已进行 LoadFun 操作 !"));
if (ObjArray_Parameter.Length != ModePassArray_Parameter.Length)
throw (new Exception(" 参数个数及其传递方式的个数不匹配 .")); // 下面是创建 MyAssemblyName 对象并设置其 Name 属性
AssemblyName MyAssemblyName = new AssemblyName();
MyAssemblyName.Name = "InvokeFun"; // 生成单模块配件
AssemblyBuilder MyAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
MyAssemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder MyModuleBuilder = MyAssemblyBuilder.DefineDynamicModule("InvokeDll"); // 定义要调用的方法 , 方法名为“ MyFun ”,返回类型是“ Type_Return ”
//参数类型是“ TypeArray_ParameterType ”
MethodBuilder MyMethodBuilder = MyModuleBuilder.DefineGlobalMethod(
"Init", MethodAttributes.Public | MethodAttributes.Static,
Type_Return, TypeArray_ParameterType); // 获取一个 ILGenerator ,用于发送所需的 IL
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("Init");
return MyMethodInfo.Invoke(null, ObjArray_Parameter);// 调用方法,并返回其值
} //Invoke方法的第二个版本,它是调用了第一个版本的:
///
/// 调用所设定的函数
///
/// < param name="IntPtr_Function" / > 函数指针
/// < param name="ObjArray_Parameter" / > 实参
/// < param name="TypeArray_ParameterType" / > 实参类型
/// < param name="ModePassArray_Parameter" / > 实参传送方式
/// < param name="Type_Return" / > 返回类型
/// 返回所调用函数的 object public object Invoke(IntPtr IntPtr_Function, object[] ObjArray_Parameter,
Type[] TypeArray_ParameterType, ModePass[] ModePassArray_Parameter,
Type Type_Return)
{ // 下面 2 个 if 是进行安全检查 , 若不能通过 , 则抛出异常
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);
} }
}
/*******调用方法******/
private void button1_Click(object sender, RoutedEventArgs e)
{ DLD newDLL = new DLD();
newDLL.LoadFun("E:\\workspaces\\WpfApplication1\\Debug\\DLL.dll", "Init");
StringBuilder MyStringBuilder = new StringBuilder("Hello World!");
object[] obj = new object[] { MyStringBuilder };
Type[] ty = new Type[] { typeof(StringBuilder) };
ModePass[] mode = new ModePass[] { ModePass.ByValue };
Type Type_Return = typeof(StringBuilder);
StringBuilder j = (StringBuilder)newDLL.Invoke(obj, ty, mode, Type_Return); }
/********c++DLL中的函数*******/ extern "C" __declspec(dllexport) LPTSTR Init(LPTSTR a); LPTSTR Init(LPTSTR a)
{
strcat((char *)a, "added");
return a;
}

【转载】C#调用C++ DLL的更多相关文章

  1. [转载] C# 调用C++ DLL 的类型转换

    //C#调用C++的DLL搜集整理的所有数据类型转换方式,可能会有重复或者多种方案,自己多测试 //c++:HANDLE(void *) ---- c#:System.IntPtr //c++:Byt ...

  2. C# 调用第三方DLL完整实例

    C# 调用第三方DLL完整实例 分类: C/C++ 以下代码为本人在实际项目中编写的调用第三方DLL接口程序的完整代码. public class ExecuteDLL : Form { ...//忽 ...

  3. 非托管C++通过C++/CLI包装调用C# DLL

    项目中要给其它客户程序提供DLL做为接口,该项目是在.Net4.0平台下开发.终所周知.Net的各个版本之间存在着兼容性的问题,但是为了使用高版本运行平台的新特性,又不得不兼顾其它低版本平台客户程序的 ...

  4. Native Application 开发详解(直接在程序中调用 ntdll.dll 中的 Native API,有内存小、速度快、安全、API丰富等8大优点)

    文章目录:                   1. 引子: 2. Native Application Demo 展示: 3. Native Application 简介: 4. Native Ap ...

  5. [转]C#调用C++dll

    本文转载至http://www.cnblogs.com/ysharp/archive/2012/05/25/2517803.html 在合作开发时,C#时常需要调用C++DLL,当传递参数时时常遇到问 ...

  6. c# 调用 C++ dll 传入传出 字符串

    c# 调用 C++ dll 传入传出 字符串 2013-07-02 09:30 7898人阅读 评论(2) 收藏 举报 本文章已收录于:   分类: windows 版权声明:随便转载,随便使用. C ...

  7. C# 中静态调用C++dll 和C# 中动态调用C++dll

    在最近的项目中,牵涉到项目源代码保密问题,由于代码是C#写的,容易被反编译,因此决定抽取核心算法部分使用C++编写,C++到目前为止好像还不能被很好的反编译,当然如果你是反汇编高手的话,也许还是有可能 ...

  8. 易语言调用外部DLL详细实例教程

    一.准备工作 一.工具:易语言 二.准备一个DLL 1)打开易语言-新建一个Windows动态链接库 2)然后右键新建一个子程序或者用快捷键:Ctrl+N .然后写上代码.我这里写一个 2个字符串拼接 ...

  9. [转]在C#中调用C语言函数(静态调用Native DLL,Windows & Microsoft.Net平台)

    原文:https://blog.csdn.net/yapingxin/article/details/7288325 对于不太了解.Net的人,如果想要了解.Net,我必须给他介绍P/Invoke.P ...

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

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

随机推荐

  1. Java如何格式化AM-PM格式的时间?

    在JAVA中,如何格式化AM-PM格式的时间? 该示例使用SimpleDateFormat(“HH-mm-ss a”)构造函数和SimpleDateFormat类的sdf.format(date)方法 ...

  2. MyBatis打印输出SQL语句

    Hibernate是可以配置 show_sql 显示 自动生成的SQL 语句,用 format_sql 可以格式化SQL 语句,但如果用 mybatis 怎么实现这个功能呢?如果你搜索看一下,基本都是 ...

  3. C# 文件过滤器filter

    OpenFileDialog对话框的Filter属性说明: 首先说明一个示例,分析一下Filter属性的构成:“ Excel文件|*.xls ”,前面的“Excel文件”成为标签,是一个可读的字符串, ...

  4. Mac homebrew类似apt-get命令安装包

    INSTALL brew ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/in ...

  5. 移动端H5地图离线瓦片方案(1)(2)

    2在作者另一篇 移动端H5地图离线瓦片方案   文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 移动端的网速和 ...

  6. 使用 StoryBoard 实现左右按钮切换图片的浏览效果

    关键技能:使用故事板进行布局时,点击选中控件(组件)并按住 control 键向某个方向拖动,产生一条实线,然后弹出的窗口可以设置控件(组件)的布局约束条件:从而实现自动布局 AutoLayout 效 ...

  7. Android开发学习笔记-SharedPreferences的用法

    SharedPreferences介绍:   做软件开发应该都知道,很多软件会有配置文件,里面存放这程序运行当中的各个属性值,由于其配置信息并不多,如果采用数据库来存放并不划算,因为数据库连接跟操作等 ...

  8. 源码分析三(Vector与ArrayList的区别)

    前面讨论过ArrayList与LinkedList的区别,ArrayList的底层数据结构是数组Object[],而LinkedList底层维护 的是一个链表Entry,所以对于查询,肯定是Array ...

  9. go反射的规则

    第一次知道反射的时候还是许多年前在学校里玩 C# 的时候.那时总是弄不清楚这个复杂的玩意能有什么实际用途……然后发现 Java 有这个,后来发现 PHP 也有了,再后来 Objective-C.Pyt ...

  10. Java使用选择排序法对数组排序

    编写程序,实现将输入的字符串转换为一维数组,并使用选择排序法对数组进行排序. 思路如下: 点击"生成随机数"按钮,创建Random随机数对象: 使用JTextArea的setTex ...