【转载】C#调用C++ DLL
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的更多相关文章
- [转载] C# 调用C++ DLL 的类型转换
//C#调用C++的DLL搜集整理的所有数据类型转换方式,可能会有重复或者多种方案,自己多测试 //c++:HANDLE(void *) ---- c#:System.IntPtr //c++:Byt ...
- C# 调用第三方DLL完整实例
C# 调用第三方DLL完整实例 分类: C/C++ 以下代码为本人在实际项目中编写的调用第三方DLL接口程序的完整代码. public class ExecuteDLL : Form { ...//忽 ...
- 非托管C++通过C++/CLI包装调用C# DLL
项目中要给其它客户程序提供DLL做为接口,该项目是在.Net4.0平台下开发.终所周知.Net的各个版本之间存在着兼容性的问题,但是为了使用高版本运行平台的新特性,又不得不兼顾其它低版本平台客户程序的 ...
- Native Application 开发详解(直接在程序中调用 ntdll.dll 中的 Native API,有内存小、速度快、安全、API丰富等8大优点)
文章目录: 1. 引子: 2. Native Application Demo 展示: 3. Native Application 简介: 4. Native Ap ...
- [转]C#调用C++dll
本文转载至http://www.cnblogs.com/ysharp/archive/2012/05/25/2517803.html 在合作开发时,C#时常需要调用C++DLL,当传递参数时时常遇到问 ...
- c# 调用 C++ dll 传入传出 字符串
c# 调用 C++ dll 传入传出 字符串 2013-07-02 09:30 7898人阅读 评论(2) 收藏 举报 本文章已收录于: 分类: windows 版权声明:随便转载,随便使用. C ...
- C# 中静态调用C++dll 和C# 中动态调用C++dll
在最近的项目中,牵涉到项目源代码保密问题,由于代码是C#写的,容易被反编译,因此决定抽取核心算法部分使用C++编写,C++到目前为止好像还不能被很好的反编译,当然如果你是反汇编高手的话,也许还是有可能 ...
- 易语言调用外部DLL详细实例教程
一.准备工作 一.工具:易语言 二.准备一个DLL 1)打开易语言-新建一个Windows动态链接库 2)然后右键新建一个子程序或者用快捷键:Ctrl+N .然后写上代码.我这里写一个 2个字符串拼接 ...
- [转]在C#中调用C语言函数(静态调用Native DLL,Windows & Microsoft.Net平台)
原文:https://blog.csdn.net/yapingxin/article/details/7288325 对于不太了解.Net的人,如果想要了解.Net,我必须给他介绍P/Invoke.P ...
- c# 调用c++DLL方法及注意事项
引用命名空间 using System.Runtime.InteropServices 调用方法: 一.静态加载 用DllImprot方式来加载c++DLL.如下格式: //对应c++方法 //voi ...
随机推荐
- linux 日志查询
tail -n 400 logname | grep "AAA" grep 简单使用 1.把要查询的行写到文本里面去: grep WXCP IC.NotifyIndexServer ...
- e740. 向标签中加入一个图标
This example creates a JLabel component with an icon. // Fetch icon Icon icon = new ImageIcon(" ...
- e613. Modifying the Focus Traversal Order
JFrame frame = new JFrame(); JButton component1 = new JButton("1"); JButton component2 = n ...
- 创建Swing的步骤
(1)导入Swing包 (2)选择界面风格 (3)设置顶层容器 (4)设置按钮和标签 (5)将组件放到容器上 (6)为组件增加边框 (7)处理事件 (8)辅助技术支持 package Com.MySw ...
- C# HttpClient请求
using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System ...
- ssh方式与服务器建立连接
package com.ustcinfo.cinas.pmng.util; import java.io.BufferedReader; import java.io.InputStream; imp ...
- 【翻译自mos文章】在RHEL7/OL7上安装Oracle 12.1.0.2的server端或者client时,报须要"compat-libstdc++"包
在RHEL7/OL7上安装Oracle 12.1.0.2的server端或者client时,报须要"compat-libstdc++"包 来源于: Installation of ...
- 【WP8】自定义EventAggregator
MVVM模式实现了ViewModel和View的分离,但是有很多时候我们需要进行页面间通信 比如,我们在设置界面修改了某个项的值,需要同步到主页面,让主页面做相关的逻辑,由于每个页面对应一个ViewM ...
- 【spark】jieba + wordcount
import sys reload(sys) sys.setdefaultencoding('utf-8') from os import path import jieba from pyspark ...
- oracle 产生随机数
-- 产生一个任意大小的随机数select dbms_random.random from dual; -- 产生一个100以内的随机数select abs(mod(dbms_random.rando ...