【C#】 使用Gsof.Native 动态调用 C动态库
【C#】 使用Gsof.Native 动态调用 C动态库
一、背景
使用C# 开发客户端时候,我们经常会调用一些标准的动态库或是C的类库。
虽然C# 提供的PInvoke的方式,但因为使用的场景的多变,有些时候可能没办法,固定位置的调用,或是需要按需求调用不同的库。 设置当前目录的方式,有时会有加载不到的问题。
CLI的方式又需要用C++做再次的封装。
二、说明
- 支持根据路径动态加载DLL类库
- 支持using 销毁加载的类库
- 调用方便
github: https://github.com/gaoshang212/gsof/tree/master/Gsof.Native
nuget: https://www.nuget.org/packages/Gsof.Native/
接口说明:
NativeFactory 创建INative调用对象:
/// <summary>
/// 创建INative 对象
/// </summary>
/// <param name="p_fileName">文件路径</param>
/// <returns></returns>
public static INative Create(string p_fileName);
/// <summary>
/// 创建INative 对象
/// </summary>
/// <param name="p_fileName">文件路径</param>
/// <param name="p_calling">调用转换方式(同PInvoke CallingConvention)/param>
/// <returns></returns>
public static INative Create(string p_fileName, CallingConvention _calling);
/// <summary>
/// 销毁INative, 也可以调用 Native的Dispose方法
/// </summary>
/// <param name="p_native"></param>
public static void Free(INative p_native);
INative:
public interface INative : IDisposable
{
/// <summary>
/// 获取函数委托
/// </summary>
/// <typeparam name="TDelegate"></typeparam>
/// <returns></returns>
TDelegate GetFunction<TDelegate>();
/// <summary>
/// 函数委托调用方式
/// </summary>
/// <typeparam name="TResult">返回值类型</typeparam>
/// <typeparam name="TDelegate">函数对应的委托类型</typeparam>
/// <param name="p_params">函数传参</param>
/// <returns></returns>
TResult Invoke<TResult, TDelegate>(params object[] p_params);
/// <summary>
/// 函数名调用
/// </summary>
/// <typeparam name="TResult">返回值类型</typeparam>
/// <param name="p_funName">函数名</param>
/// <param name="p_params">函数传参</param>
/// <returns></returns>
TResult Invoke<TResult>(string p_funName, params object[] p_params);
/// <summary>
/// 函数名调用
/// </summary>
/// <typeparam name="TResult">返回值类型</typeparam>
/// <param name="p_funName">函数名</param>
/// <param name="p_calling">调用转换方式(同PInvoke CallingConvention)</param>
/// <param name="p_params">函数传参</param>
/// <returns></returns>
TResult Invoke<TResult>(string p_funName, CallingConvention p_calling, params object[] p_params);
/// <summary>
/// 函数名调用(非泛型)
/// </summary>
/// <param name="p_funName">函数名</param>
/// <param name="p_retrunType">返回值类型</param>
/// <param name="p_params">函数传参</param>
/// <returns></returns>
object Invoke(string p_funName, Type p_retrunType, params object[] p_params);
/// <summary>
/// 函数委托调用方式
/// </summary>
/// <typeparam name="TDelegate">函数对应的委托类型</typeparam>
/// <param name="p_params">函数传参</param>
void Call<TDelegate>(params object[] p_params);
/// <summary>
/// 函数名调用
/// </summary>
/// <param name="p_funName">函数名</param>
/// <param name="p_params">函数传参</param>
void Call(string p_funName, params object[] p_params);
/// <summary>
/// 函数名调用
/// </summary>
/// <param name="p_funName">函数名</param>
/// <param name="p_calling">调用转换方式(同PInvoke CallingConvention)</param>
/// <param name="p_params">函数传参</param>
void Call(string p_funName, CallingConvention p_calling, params object[] p_params);
}
三、使用
libtest.dll 为 中包括一个test函数
int test(int input)
{
return input;
}
方法名调用
int input = 0;
int result = -1;
using (var native = NativeFactory.Create(@"../../libtest.dll"))
{
result = native.Invoke<int>("test", input);
}
dynamic 方式调用
- 优点:调用方便,简单类型调用时,不用做过多的定义。
- 缺点:4.0下性能不理想,4.5+性能好很多,但相较于委托的方式,还差些。
int input = 0;
int result = -1;
using (dynamic native = NativeFactory.Create(@"../../libtest.dll"))
{
result = native.test<int>(input);
}
委托方式调用
- 优化:效率高,没有了第一次动态构造委托的消耗,可获取到函数委托增加 重复调用消耗
- 缺点:如果函数较多,委托定义较为繁琐
[NativeFuncton("test")]
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate int Test(int p_sleep);
public void DelegateFunction()
{
int input = 0;
int result = -1;
using (var native = NativeFactory.Create(@"../../libtest.dll"))
{
// 直接调用
var result1 = native1.Invoke<int, Test>(input);
// 获取函数委托调用
var test = native.GetFunction<Test>();
result = test(input);
}
Assert.AreEqual(input, result);
}
【C#】 使用Gsof.Native 动态调用 C动态库的更多相关文章
- WCF 动态调用(动态创建实例接口)
很多时候,服务地址都不止一个的,这个时候就要动态去配置地址.配置Web.config,很麻烦 下面就看看怎样实现动态调用WCF. 首先看看动态创建服务对象的代码: using System; usin ...
- C# 直接调用vs 委托vs动态调用vs动态类型vs反射,最佳性能测试
懒得解释,自己看代码 测试结果: Direct call:00:00:00.0742191Delegate Direct:00:00:00.0687487Method Factory(IL):00:0 ...
- c# 动态调用.net编写的webservices接口
创建类WebServiceHelper: public class WebServiceHelper { #region 动态调用WebService动态调用地址 /// < summary&g ...
- C# WebService动态调用
前言 站在开发者的角度,WebService 技术确实是不再“时髦”.甚至很多人会说,我们不再用它.当然,为了使软件可以更简洁,更有层次,更易于实现缓存等机制,我是非常建议将 SOAP 转为 REST ...
- c/c++ 继承与多态 静态调用与动态调用
静态调用,与动态调用. 动态调用条件:必须用父类的引用或者指针,并且调用的必须是虚方法. #include <iostream> class Base{ public: virtual i ...
- (23) java web的struts2框架的使用-struts动态调用和通配符
一,动态查找 1,配置允许动态调用 <!-- 允许动态方法调用 --> <constant name="struts.enable.DynamicMethodInvocat ...
- C# 中静态调用C++dll 和C# 中动态调用C++dll
在最近的项目中,牵涉到项目源代码保密问题,由于代码是C#写的,容易被反编译,因此决定抽取核心算法部分使用C++编写,C++到目前为止好像还不能被很好的反编译,当然如果你是反汇编高手的话,也许还是有可能 ...
- .net WebServer示例及调用(接口WSDL动态调用 JAVA)
新建.asmx页面 using System; using System.Collections.Generic; using System.Linq; using System.Web; using ...
- 调用webservice服务(通过反射的方式动态调用)
调用 ";//系统类别 var jkxlh = "";//接口序列号 var jkid = "68W05";//接口id string WriteXm ...
随机推荐
- python大法好——递归、内置函数、函数进阶
1.递归(自己干自己) def fun(n): n=n/2 print(n) if(n>2) fun(n) #函数调用 fun(10) 结果是5 2 1 0 递归的执行过程:递归执行到最里面一层 ...
- linux安装jdk8
1.文件准备 jdk-8u201-linux-x64.tar.gz 下载地址 http://www.oracle.com/technetwork/java/javase/downloads/jdk8- ...
- Android 查阅博客1_app优化_1大小
Android App Bundle (google play 商店发布应用的话,可自行深入了解下,这里不做介绍) http://mp.weixin.qq.com/s?__biz=MzAwODY4 ...
- Add Inline Actions
[Add Inline Actions] 1.为了使用 inline action,需要给 eosio.code 账号添加active权限. To use the 'activeauthority i ...
- Python学习—基础篇之基本数据类型(一)
数据类型 在python中,能够直接处理的基本数据类型主要有数字类型.字符串类型.字节类型.布尔类型.列表.元组.字典.集合等. 一.数字类型 1.1 数字类型的创建 # 数字类型 a = 10 b ...
- 连续子数组最大和(python)
题目描述 HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决.但是,如果向量 ...
- 【转载】重置密码解决MySQL for Linux错误 ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
重置密码解决MySQL for Linux错误 ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using passwor ...
- Go学习笔记:Win7+LiteIDE+Go+Beego 环境搭建
安装过程比较简单 1.安装go语言环境: 2.安装git: 3.git bash 安装beego,输入“go get github.com/astaxie/beego”,等待一会儿,在D盘的 ...
- Django formset
一 什么是formset Form组件或ModelForm用于做一个表单验证而formset是用于做多个表单的验证组件,用于做批量操作 二 formset的使用方法 1 设置form信息 class ...
- SQL Server 2008 R2 根据WSDL访问WebService
参考网站:WebService学习整理(一)——客户端三种调用方式整理 自我概括: WebService 通过HTTP通讯,数据以XML格式传输使两个系统进行数据交互 SOAP 是访问协议(注明访问W ...