手工生成DuckDB 1.4版c++插件的简单步骤

  1. 到https://github.com/duckdb/extension-template 下载模板源代码压缩包, 把其中的src目录解压缩到/par/cppext14

  2. 到https://github.com/duckdb/duckdb/releases 下载1.4版动态库和静态库压缩包, 解压缩到/par/libduckdb

  3. 到https://github.com/duckdb/extension-ci-tools 下载https://github.com/duckdb/extension-ci-tools/blob/main/scripts/append_extension_metadata.py 文件到/par。

  4. 编译

g++ -fPIC -shared -o libtest2.so quack_extension.cpp -I /par/libduckdb -lssl -lcrypto -I include -lduckdb -L /par/libduckdb
编译出错,

quack_extension.cpp:5:10: fatal error: duckdb/common/exception.hpp: No such file or directory
    5 | #include "duckdb/common/exception.hpp"

将quack_extension.cpp中如下3行注释掉,因为他们的内容在动态库自带的duckdb.hpp都有。

//#include "duckdb/common/exception.hpp"
//#include "duckdb/function/scalar_function.hpp"
//#include <duckdb/parser/parsed_data/create_scalar_function_info.hpp>

5.添加元数据
注意要把版本号写为v1.4.0

root@6ae32a5ffcde:/par/agg# python3 /par/appendmetadata.py -l libtest2.so -n quack -dv v1.4.0  --duckdb-platform linux_amd64 --extension-version 0.1 --abi-type ""
Creating extension binary:
 - Input file: libtest2.so
 - Output file: quack.duckdb_extension
 - Metadata:
   - FIELD8 (unused)            = EMPTY
   - FIELD7 (unused)            = EMPTY
   - FIELD6 (unused)            = EMPTY
   - FIELD5 (abi_type)          =
   - FIELD4 (extension_version) = 0.1
   - FIELD3 (duckdb_version)    = v1.4.0
   - FIELD2 (duckdb_platform)   = linux_amd64
   - FIELD1 (header signature)  = 4 (special value to identify a duckdb extension)

8.加载运行
因为动态库不在搜索路径,所以直接加载报错,设置环境变量LD_LIBRARY_PATH就好了

root@6ae32a5ffcde:/par/cppext14/src# /par/duckdb140 -unsigned
DuckDB v1.4.0 (Andium) b8a06e4a22
Enter ".help" for usage hints.
D load '/par/cppext14/src/quack.duckdb_extension';
IO Error:
Extension "/par/cppext14/src/quack.duckdb_extension" could not be loaded: libduckdb.so.1.4: cannot open shared object file: No such file or directory
D .exit

root@6ae32a5ffcde:/par/cppext14/src# export LD_LIBRARY_PATH=/par/libduckdb

root@6ae32a5ffcde:/par/cppext14/src# /par/duckdb140 -unsigned
DuckDB v1.4.0 (Andium) b8a06e4a22
Enter ".help" for usage hints.
D load '/par/cppext14/src/quack.duckdb_extension';
D select quack('asdf');
┌───────────────┐
│ quack('asdf') │
│    varchar    │
├───────────────┤
│ Quack asdf 🐥 │
└───────────────┘
D select quack_openssl_version('abcd');
┌────────────────────────────────────────────────────────────────────┐
│                   quack_openssl_version('abcd')                    │
│                              varchar                               │
├────────────────────────────────────────────────────────────────────┤
│ Quack abcd, my linked OpenSSL version is OpenSSL 3.0.15 3 Sep 2024 │
└────────────────────────────────────────────────────────────────────┘

以上步骤比官方步骤最大的优势是不用编译DuckDB源代码,节省大量时间,等开发测试完成,正式发布前再用官方步骤执行。
我曾经想用链接静态库libduckdb_static.a来编译,结果编出来的文件大了许多,ldd看也不依赖duckdb动态库,但是仍然缺少符号,看来静态库里的函数不如动态库全。

root@6ae32a5ffcde:/par/cppext14/src# mv quack.duckdb_extension quack.duckdb_extension.14

root@6ae32a5ffcde:/par/cppext14/src# g++ -fPIC -shared -o libtest2.so quack_extension.cpp -I /par/libduckdb -lssl -lcrypto -I include  /par/libduckdb/libduckdb_static.a
root@6ae32a5ffcde:/par/cppext14/src# python3 /par/appendmetadata.py -l libtest2.so -n quack -dv v1.4.0  --duckdb-platform linux_amd64 --extension-version 0.1 --abi-type ""
Creating extension binary:
 - Input file: libtest2.so
 - Output file: quack.duckdb_extension
 - Metadata:
   - FIELD8 (unused)            = EMPTY
   - FIELD7 (unused)            = EMPTY
   - FIELD6 (unused)            = EMPTY
   - FIELD5 (abi_type)          =
   - FIELD4 (extension_version) = 0.1
   - FIELD3 (duckdb_version)    = v1.4.0
   - FIELD2 (duckdb_platform)   = linux_amd64
   - FIELD1 (header signature)  = 4 (special value to identify a duckdb extension)
root@6ae32a5ffcde:/par/cppext14/src# ls -l quack.duckdb_extension*
-rwxrwxrwx 1 root root 37309110 Sep 29 12:54 quack.duckdb_extension
-rwxrwxrwx 1 root root   222182 Sep 29 12:39 quack.duckdb_extension.14
root@6ae32a5ffcde:/par/cppext14/src# /par/duckdb140 -unsigned
DuckDB v1.4.0 (Andium) b8a06e4a22
Enter ".help" for usage hints.
D load '/par/cppext14/src/quack.duckdb_extension';
IO Error:
Extension "/par/cppext14/src/quack.duckdb_extension" could not be loaded: /par/cppext14/src/quack.duckdb_extension: undefined symbol: _ZN10duckdb_fmt2v68internal10basic_dataIvE6digitsE
D .exit
root@6ae32a5ffcde:/par/cppext14/src# ldd quack.duckdb_extension
        linux-vdso.so.1 (0x00007fff8cfd2000)
        libssl.so.3 => /lib/x86_64-linux-gnu/libssl.so.3 (0x00007f297d687000)
        libcrypto.so.3 => /lib/x86_64-linux-gnu/libcrypto.so.3 (0x00007f297d201000)
        libstdc++.so.6 => /usr/local/lib64/libstdc++.so.6 (0x00007f297cf93000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f297ceb3000)
        libgcc_s.so.1 => /usr/local/lib64/libgcc_s.so.1 (0x00007f297ce86000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f297cca2000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f297f514000)
root@6ae32a5ffcde:/par/cppext14/src# ldd quack.duckdb_extension.14
        linux-vdso.so.1 (0x00007ffe62ded000)
        libssl.so.3 => /lib/x86_64-linux-gnu/libssl.so.3 (0x00007fd662763000)
        libcrypto.so.3 => /lib/x86_64-linux-gnu/libcrypto.so.3 (0x00007fd6622dd000)
        libduckdb.so.1.4 => /par/libduckdb/libduckdb.so.1.4 (0x00007fd65ec99000)
        libstdc++.so.6 => /usr/local/lib64/libstdc++.so.6 (0x00007fd65ea2b000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd65e94b000)
        libgcc_s.so.1 => /usr/local/lib64/libgcc_s.so.1 (0x00007fd65e91c000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd65e73a000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd65e735000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd65e730000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fd662841000)

用工具查看,确实如此

root@6ae32a5ffcde:/par/cppext14/src# readelf -c /par/libduckdb/libduckdb_static.a |grep _ZN10duckdb_fmt2v68internal10basic_dataIvE6digitsE

root@6ae32a5ffcde:/par/cppext14/src# nm -D /par/libduckdb/libduckdb.so |grep _ZN10duckdb_fmt2v68internal10basic_dataIvE6digitsE
0000000003432280 u _ZN10duckdb_fmt2v68internal10basic_dataIvE6digitsE
### DuckDB C++ 库的使用方法 DuckDB 是一种嵌入式的SQL数据库管理系统,支持多种编程语言接口,其中包括C++。为了在项目中集成并使用DuckDB C++库,通常需要完成以下几个方面的工作: #### 安装依赖项与获取源码 对于希望从头构建环境的情况,可以通过Git克隆官方仓库来获得最新本的DuckDB源代码[^4]。 ```bash git clone https://github.com/duckdb/duckdb.git ``` #### 构建过程配置 当涉及到具体项目的编译时,推荐采用`CMake`作为跨平台的构建工具。这不仅简化了不同操作系统间的移植工作,还允许更灵活地管理第三方依赖关系以及优化选项设置。针对观察到的不同编译器产生的二进制文件体积差异现象,在实际操作过程中可以尝试调整链接阶段所引入静态库的数量以控制最终产物大小[^2]。 #### 初始化连接实例 下面给出了一段简单的示例程序用于展示如何创建一个新的DuckDB数据库连接对象,并执行基本查询命令: ```cpp #include "duckdb.hpp" using namespace duckdb; int main(int argc, char *argv[]) { try { // 创建新的内存中的数据库实例 unique_ptr<DuckDB> db(DuckDB::Open(":memory:")); // 开启新事务 Connection con(*db); // 执行DDL语句创建表结构 con.Query("CREATE TABLE integers(i INTEGER);"); // 插入测试数据记录 con.Query("INSERT INTO integers VALUES (42), (87);"); // 查询刚刚插入的数据集 auto result = con.Query("SELECT i FROM integers ORDER BY i;"); // 输出结果至标准输出流 while(result->Next()) { printf("%d\n", result->GetValue<int>(0)); } } catch (...) { fprintf(stderr,"An error occurred during execution.\n"); return EXIT_FAILURE; } return EXIT_SUCCESS; } ``` 此代码片段展示了通过调用`DuckDB::Open()`函数打开指定路径下的持久化存储文件(此处为`:memory:`表示仅存在于运行期间),之后利用`Connection`类来进行各类SQL指令交互[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值