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. JUnit教程

    测试是检查应用程序是否是工作按照要求,并确保在开发者水平,单元测试进入功能性的处理.单元测试是单一实体(类或方法)的测试. 单元测试在每一个软件公司开发高品质的产品给他们的客户是十分必要的. 单元测试 ...

  2. Spring Boot 快速搭建的三种方式

    方式一:http://start.spring.io/ 打开浏览器,在地址栏中输入http://start.spring.io/ 如下图:  点击generate project 然后就会有一个zip ...

  3. Kong安装简介

    评价:其实是一个整合型的方案,从它的安装页面看:http://getkong.org/download/#other该方案基于OpenResty,和lua 提供的功能是统一的Oauth认证.rest封 ...

  4. Xcode : svn 无法上传静态库(.a)文件

    1.打开终端,输入cd,空格,然后将需要上传的.a文件所在的文件夹(不是.a文件)拖拽到终端(此办法无需输入繁琐的路径,快捷方便) ,回车:2.之后再输入如下命令:svn add xxx.a,回车:3 ...

  5. Logback中文文档(四):Appender

    什么是 Appender Appender是负责写记录事件的组件.Appender 必须实现接口"ch.qos.logback.core.Appender".该接口的重要方法总结如 ...

  6. 多个table 相同col 的 设置相同width

    不同table 中的col 虽然设置了width 相同,但在IE8.9中长度仍不统一.经检查是不同table使用了不同的colspan ,删除colspan全部使用<td></td& ...

  7. Effective STL读书笔记

    Effective STL 读书笔记 本篇文字用于总结在阅读<Effective STL>时的笔记心得,只记录书上描写的,但自己尚未熟练掌握的知识点,不记录通用.常识类的知识点. STL按 ...

  8. 17 HTTP编程入门

    http请求原理 http请求原理我就不多说了,网上一搜就能搜索到,下面我注意是记录下http模块的使用方法 http 模块 HTTP-server hello world 我们使用HandleFun ...

  9. BarTender 2016表单中的“秤显示”控件

    BarTender 2016中的表单是一个非常实用的工具,它可以实现数据输出提示,查询提示和同一表单的记录选择.这些都离开可供添加的控件,“秤显示”控件也是我们打印尝尝需要涉及的,今天我们就来看看什么 ...

  10. Python+Django(Python Web项目初体验)

    参考:https://blog.csdn.net/qq_34081993/article/details/79229784 Django是一个开放源代码的Web应用框架,由Python写成. 安装Dj ...