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 如果当前目录有 ...
随机推荐
- Archlinux常用软件推荐 更新于2022年5月
必装软件# xdg-user-dirs-gtk 执行 xdg-user-dirs-gtk-update 可将更新Home目录路径 包管理工具# yay 代替pacman的包管理 downgrade p ...
- 【转载】Spring Cloud Gateway-路由谓词工厂详解(Route Predicate Factories)
http://www.imooc.com/article/290804 TIPS 本文基于Spring Cloud Greenwich SR2编写,兼容Spring Cloud Finchley及更高 ...
- Qt编写地图综合应用41-在线轮廓图
一.前言 轮廓图也叫行政区划,这里的轮廓图是指百度地图的区域轮廓图,不是之前文章中提到的echart专用的轮廓图,百度地图的轮廓图就是一个不规则的多边形区域,只不过这个区域的坐标点一般是特别多的,比如 ...
- Qt开发经验小技巧101-110
如果需要在尺寸改变的时候不重绘窗体,则设置属性即可 this->setAttribute(Qt::WA_StaticContents, true); 这样可以避免可以避免对已经显示区域的重新绘制 ...
- C# .Net FrameWork3.5中异步HTTP请求时,由于安全协议的问题System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)方法抛出“基础连接已经关闭: 发送时发生错误”的解决办法
现象描述: C# .Net FrameWork3.5中异步HTTP请求时,由于安全协议的问题System.Net.HttpWebRequest.EndGetResponse(IAsyncResult ...
- Golang基础-字节跳动青训营
Golang 安装 访问 https://go.dev/ ,点击 Download ,下载对应平台安装包,安装即可 如果无法访问上述网址,可以改为访问 https://studygolang.com/ ...
- 注册表判断是否安装微软Edge浏览器
自己摸索的,注册表判断是否安装微软Edge浏览器: bool checkInstalledMsEdge() { try { using(var ieKey = Registry.LocalMachin ...
- Linux 常用脚本命令-lsof、find、rpm、SS、top、vim
1,关机命令 1 shutdown -h now/0 2 halt 3 init 0 4 poweroff 5 举例: 6 shutdown -h 3 ------3分钟后关机(可用shutdown ...
- WebSocket一篇就够了-copy
WebSocket介绍与原理 WebSocket protocol 是HTML5一种新的协议.它实现了浏览器与服务器全双工通信(full-duplex).一开始的握手需要借助HTTP请求完成. --百 ...
- consul简介
Consul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置. Consul是分布式的.高可用的.可横向扩展的.它具备以下特性 : 服务发现:consul通过DNS或者HTT ...