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. webpy 使用python3开发

    由于做服务器时总是需要调式与客户端的各种协议,由于种种原因客户端总是滞后的.所以一直想做个协议调试工具.postman是一个好东西,不过如果前后协议之间有关联,就不是很好用了. 之前用python写过 ...

  2. Java调试那点事[转]

    转自云栖社区:https://yq.aliyun.com/articles/56?spm=5176.100239.blogcont59193.11.jOh3ZG# 摘要: 该文章来自于阿里巴巴技术协会 ...

  3. 一篇关于apache commons类库的详解[转]

    1.1. 开篇 在Java的世界,有很多(成千上万)开源的框架,有成功的,也有不那么成功的,有声名显赫的,也有默默无闻的.在我看来,成功而默默无闻的那些框架值得我们格外的尊敬和关注,Jakarta C ...

  4. Maven最佳实践-distributionManagement

    分发构件至远程仓库 mvn install 会将项目生成的构件安装到本地Maven仓库,mvn deploy 用来将项目生成的构件分发到远程Maven仓库.本地Maven仓库的构件只能供当前用户使用, ...

  5. SVN自动生成版本号信息

        在平时的多版本开发过程中,需要通过版本号来定位到源码版本,便于定位问题.常规工程实践是设置版本号为X.Y.Z.N,一般X表示主版本号,Y表示子版本号,我一般将Z设为0,N为本次提交的SVN版本 ...

  6. HTML5 touche vents drag to move & AF actionsheet by longTap

    $('img').on("touchstart",function(E){ //E.preventDefault();E.stopPropagation(); var el=thi ...

  7. spring mvc 框架URL接收中文参数的乱码解决方案

    后台可能就会出现乱码,具体解决方案如下: 一. 配置tomcat目录下的service.xml文件 tomcat7/conf/server.xml 给该行代码加上 URIEncoding=" ...

  8. 【DeepLearning】汉字手写体识别

    http://blog.topspeedsnail.com/archives/10897 两个双卷积池化 + dropout + 2个全链接 + softmax

  9. 图解HTTP学习笔记——简单的HTTP协议

    简单的HTTP协议 前言 最近在学习Web开发的相关知识,发现<图解HTTP>这本书通俗易懂.所以花时间学习这本书,并记录下学习笔记. 如上图,我们每天都在浏览网页,一般我们都是在浏览器地 ...

  10. Postman测试api@RequestBody接收参数

    api postman 结果 { , "message": "Content type 'multipart/form-data;boundary=----------- ...