C#跨平台P/Invoke时导入动态库的问题
众所周知C#的DllImport特性只允许将常量字符串赋值给DllName。
C/C++动态库在不同平台上可能具有不同的名称。
用nativedep这个库来举例:在windows上可能叫nativedep.dll、linux上叫libnativedep.so、macos上叫libnativedep.dylib。
幸运的是C#会处理常见的变体,如果使用nativedep作为DllName,以上变体都能正确匹配:
[DllImport("nativedep")]
static extern int ExportedFunction();
在 Windows 上运行时,将按以下顺序搜索 DLL:
nativedep
nativedep.dll(如果库名称尚未以 .dll 或 .exe 结尾)
在 Linux 或 macOS 上运行时,运行时将尝试在 lib 前添加,并追加规范共享库扩展。 在这些 OS 上,按以下顺序尝试库名称变体:
nativedep.so / nativedep.dylib
libnativedep.so / libnativedep.dylib 1
nativedep
libnativedep 1
在 Linux 上,如果库名称以 .so 结尾或包含 .so.(注意尾随 .),则搜索顺序会有所不同。 请考虑以下示例:
C#
[DllImport("nativedep.so.6")]
static extern int ExportedFunction();
在这种情况下,将按以下顺序尝试库名称变体:
nativedep.so.6
libnativedep.so.6 1
nativedep.so.6.so
libnativedep.so.6.so 1
仅当库名称不包含目录分隔符 (/) 时才检查路径。
但不幸的是有些库作者不按常理命名,导致默认的行为不管用,比如使用“libnativedep-0.dll”这种名称。这时可以考虑使用 NativeLibrary.SetDllImportResolver 来自定义解析规则。
如果你的库面向standard2.0、standard2.1,那么 NativeLibrary.SetDllImportResolver 是用不了的。一个可以考虑的做法是手动改掉c/c++动态库的名称使其匹配默认规则,前提是库内部不会依赖文件名称;
另一个做法是使用kernel32.LoadLibrary、libdl.dlopen封装一个中间层。可参考 https://github.com/mellinoe/nativelibraryloader。
相关资料:
SetDllImportResolver不支持.NET Standard
一个曾经踩坑的开源库,查看提交记录363a555d可以看到作者采用了两种方式
C#跨平台P/Invoke时导入动态库的问题的更多相关文章
- Linux下Gcc生成和使用静态库和动态库详解(转)
一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同( ...
- Linux下Gcc生成和使用静态库和动态库详解
参考文章:http://blog.chinaunix.net/uid-23592843-id-223539.html 一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库 ...
- 【转】分析Linux和windows动态库
原文地址:http://www.cnblogs.com/chio/archive/2008/11/13/1333119.html 摘要:动态链接库技术实现和设计程序常用的技术,在Windows和Lin ...
- [转]Linux下用gcc/g++生成静态库和动态库(Z)
Linux下用gcc/g++生成静态库和动态库(Z) 2012-07-24 16:45:10| 分类: linux | 标签:链接库 linux g++ gcc |举报|字号 订阅 ...
- Linux-Gcc生成和使用静态库和动态库详解
一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同( ...
- linux静态与动态库创建及使用实例
一,gcc基础语法: 基本语法结构:(由以下四部分组成) gcc -o 可执行文件名 依赖文件集(*.c/*.o) 依赖库文件及其头文件集(由-I或-L与-l指明) gcc 依赖文件集(*.c/*.o ...
- Linux和windows动态库
转载:http://www.cnblogs.com/chio/archive/2008/11/13/1333119.html 态链接库技术实现和设计程序常用的技术,在Windows和Linux系 统中 ...
- 修改OpenSSL默认编译出的动态库文件名称
在 Windows 平台上调用动态链接库 dll 文件时,有两种方式:a) 隐式的加载时链接:使用 *.lib (导入库)文件,在 IDE 的链接器相关设置中加入导入库 lib 文件的名称,或在程序中 ...
- 【转】Linux下gcc生成和使用静态库和动态库详解
一.基本概念 1.1 什么是库 在Windows平台和Linux平台下都大量存在着库. 本质上来说,库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不 ...
- linux动态库与静态库混合连接
1, 在应用程序需要连接外部库的情况下,linux默认对库的连接是使用动态库,在找不到动态库的情况下再选择静态库.使用方式为: gcc test.cpp -L. -ltestlib 如果当前目录有 ...
随机推荐
- spring 项目实现带请求链路id的日志记录
我们在做java项目的时候通常需要通过请求日志来排查定位线上问题,在日志比较多而我们又需要查找整个请求的全部日志的时候会比较困难.所以,就需要在日志记录的时候讲同一个请求的关键日志用同一个唯一标识串联 ...
- 如何用source和source结合cat << EOF 和EOF )实现template.txt模板文件变量的替换
使用 source 和 cat << EOF 来实现 template.txt 模板文件变量的替换,你可以按照以下步骤操作: 创建 config.env 文件:包含变量定义. 创建 tem ...
- Spring Boot + K8S 中的滚动发布、优雅停机、弹性伸缩、应用监控、配置分离
前言 K8s + SpringBoot实现零宕机发布:健康检查+滚动更新+优雅停机+弹性伸缩+Prometheus监控+配置分离(镜像复用) 配置 健康检查 健康检查类型:就绪探针(readiness ...
- RedisTemplate配置的jackson.ObjectMapper里的一个enableDefaultTyping方法过期解决
1.前言 最近升级SpringBoot,从2.1.6版本升级到2.2.6版本,发现enableDefaultTyping方法过期过期了. 该方法是指定序列化输入的类型,就是将数据库里的数据安装一定类型 ...
- H2数据UNIX_TIMESTAMP兼容问题
开篇 今天某同事在spring结合H2实现mybatis DAO层单测的时候遇到一个问题,本着人道主义临时支持下我司大xx业务,就帮忙一起看了下,回想一下整个过程还是挺有意思的,就顺便写了这篇文章来 ...
- 『玩转Streamlit』--集成Plotly
之前介绍了如何在Streamlit App中使用Matplotlib库来绘图. 本篇介绍 Steamlit结合Poltly的方法,相比于Matplotlib,Poltly的交互性更强, 更适合在Web ...
- 快速生成视频互动直播包含会议直播APP(Android)
阿里云服务器推荐购买99元 首先此应用基于腾讯云实时音视频TRTC.注册腾讯云https://console.cloud.tencent.com/trtc 并完成实名认证开始. 安卓直播高级版 包括直 ...
- Qt编写地图综合应用25-echart动态交互
一.前言 之前用echart组件做过各种效果,随着各种现场应用现场项目的增多,各种需求也都慢慢增加起来,为了满足各种不同类型的需求,近期又抽空重新整理和封装了echart类,主要就是增加了不少的js函 ...
- vue3项目实战+element-plus
记录自己搭建前端项目的学习过程和开发过程,希望一起学习进步 采用Vue3+element-plus+axios+vue-router+sass--(目前刚开始是用到了这些,随着开发慢慢更新) npm是 ...
- shell脚本检查192.168.1网段ip是否在用
要检查 192.168.1 网段中哪些 IP 地址正在使用,可以使用 Shell 脚本结合 ping 命令来扫描整个网段.以下是实现这一功能的完整脚本: 脚本:检查 192.168.1 网段 IP 是 ...