8 个版本
0.3.4 | 2024 年 7 月 31 日 |
---|---|
0.3.3 | 2024 年 7 月 8 日 |
0.3.1 | 2024 年 6 月 30 日 |
0.3.0 | 2024 年 5 月 27 日 |
0.1.1 | 2024 年 5 月 14 日 |
在 开发工具 中排名第 504
每月下载量 302
24KB
453 行
dlwrap
在创建支持多个后端(如 压缩、加密等)的应用程序时,有时不希望一次性将所有支持的库链接到应用程序中。
使用 dlopen
,可以在第一次调用库中的函数时延迟加载库。这种机制通常通过围绕库函数的包装器来实现,尽管编写包装器既繁琐又容易出错。
dlwrap
使应用程序实现此机制变得简单。
用法
让我们考虑一个假设的应用程序,它调用 ZSTD_versionNumber
和 ZSTD_versionString
来检索 ZSTD 库的运行时版本。
首先创建一个源文件 zstdver.c
,内容如下:
#include "zstdwrap.h"
#include <stdio.h>
int
main (void)
{
unsigned v1 = ZSTDWRAP_FUNC(ZSTD_versionNumber)();
printf ("ZSTD_versionNumber: %u\n", v1);
const char *v2 = ZSTDWRAP_FUNC(ZSTD_versionString)();
printf ("ZSTD_versionString: %s\n", v2);
return 0;
}
需要注意以下几点
- 不是标准的
<zstd.h>
头文件,而是包含"zstdwrap.h"
- 使用
ZSTDWRAP_FUNC
宏包装函数符号
现在继续生成辅助文件
$ cargo install dlwrap
$ dlwrap --input /usr/include/zstd.h \
--output-dir out \
--clang-resource-dir "$(clang -print-resource-dir)" \
--loader-basename zstdwrap \
--symbol-regex "^ZSTD_(versionNumber|versionString)$" \
--prefix zstdwrap \
--include "<zstd.h>"
此命令将在 out/
下创建 3 个文件:zstdwrap.c
、zstdwrap.h
和 zstdwrapfuncs.h
。
此时,应用程序可以编译为
$ gcc -pthread -I./out \
-DZSTDWRAP_ENABLE_DLOPEN=1 \
-DZSTDWRAP_SONAME='"libzstd.so.1"' \
-DZSTDWRAP_ENABLE_PTHREAD=1 \
-o zstdver examples/zstdver.c out/zstdwrap.c
生成的代码提供了一些配置宏
-
<LIBRARY_PREFIX>_ENABLE_DLOPEN
控制是否启用此dlopen
机制。如果它未定义或为 0,则应用程序需要在构建时链接到所需的库(见下文)。这对于根据是否支持dlopen
的平台条件化构建非常有用。 -
<LIBRARY_PREFIX>_SONAME
指定了dlopen
的第一个参数。如果它未定义,则不会自动加载库,应用程序需要调用<library_prefix>_ensure_library
函数,该函数将库SONAME作为第一个参数。这在应用程序在运行时确定实际库时很有用。 -
<LIBRARY_PREFIX>_ENABLE_PTHREAD
控制自动库加载是否应为线程安全;在这种情况下,使用pthread_once
来保护库加载和符号解析。
使用ldd
检查zstdver
可执行文件时,您会看到libzstd.so.1
没有链接,但它似乎已经链接了。
$ ldd zstdver
linux-vdso.so.1 (0x00007ffc705bf000)
libc.so.6 => /lib64/libc.so.6 (0x00007f8a1199f000)
/lib64/ld-linux-x86-64.so.2 (0x00007f8a11ba3000)
$ ./zstdver
ZSTD_versionNumber: 10506
ZSTD_versionString: 1.5.6
$ ltrace -e dlopen ./zstdver
zstdver->dlopen("libzstd.so.1", 1) = 0x13152c0
ZSTD_versionNumber: 10506
ZSTD_versionString: 1.5.6
+++ exited (status 0) +++
未定义ZSTDWRAP_ENABLE_DLOPEN
,相同的应用程序代码可以用标准链接方式编译(即在构建时链接libzstd
)。
$ gcc -I./out \
-o zstdver examples/zstdver.c out/zstdwrap.c \
-lzstd
$ ldd ./zstdver
linux-vdso.so.1 (0x00007ffcd43e4000)
libzstd.so.1 => /lib64/libzstd.so.1 (0x00007f7323269000)
libc.so.6 => /lib64/libc.so.6 (0x00007f7323087000)
/lib64/ld-linux-x86-64.so.2 (0x00007f732334a000)
$ ltrace -e dlopen ./zstdver
ZSTD_versionNumber: 10506
ZSTD_versionString: 1.5.6
+++ exited (status 0) +++
许可协议
Apache-2.0
生成的代码可以在FSFAP下分发。
依赖关系
~4–5.5MB
~97K SLoC