测试duckdb的C插件模板的编译加工和加载
首先下载2个压缩包,第一个是模板,第二个是所需工具
从 https://github.com/duckdb/extension-template-c 下载 extension-template-c-main.tar.gz
从 https://github.com/duckdb/extension-ci-tools 下载 extension-ci-tools-main.tar.gz
分别解压,然后把第二个解压出的内容放到第一个的extension-ci-tools空目录下。
首先尝试页面介绍的正规做法
make configure
python3 -m venv configure/venv
The virtual environment was not created successfully because ensurepip is not
available. On Debian/Ubuntu systems, you need to install the python3-venv
package using the following command.apt install python3.11-venvYou may need to use sudo with that command. After installing the python3-venv
package, recreate your virtual environment
按照提示安装python3.11-venv
apt install python3.11-venv
...
Setting up python3-setuptools-whl (66.1.1-1+deb12u2) ...
Setting up python3-pip-whl (23.0.1+dfsg-1) ...
Setting up libpython3.11-minimal:amd64 (3.11.2-6+deb12u6) ...
Setting up python3.11-minimal (3.11.2-6+deb12u6) ...
Setting up libpython3.11-stdlib:amd64 (3.11.2-6+deb12u6) ...
Setting up python3.11 (3.11.2-6+deb12u6) ...
Setting up python3.11-venv (3.11.2-6+deb12u6) ...
再次
make configure
Traceback (most recent call last):File "/par/extension-template-c-main/extension-ci-tools/scripts/configure_helper.py", line 44, in <module>main()File "/par/extension-template-c-main/extension-ci-tools/scripts/configure_helper.py", line 36, in mainimport duckdb
ModuleNotFoundError: No module named 'duckdb'
我只是要编译一个c插件,还要装python的duckdb模块, 太复杂了,放弃了。
看到extension-template-c-main目录下有个CMakeLists.txt,想到用cmake,
mkdir build
/par/extension-template-c-main# cd build
/par/extension-template-c-main/build# cmake ..
CMake Error at CMakeLists.txt:8 (message):DuckDB extension name is required-- Configuring incomplete, errors occurred!
我也不知道cmake在哪设置DuckDB extension name,也放弃了。
那就用平常编译c项目的方法,自己写gcc命令行。
看了看目录结构,源代码在extension-template-c-main/src下,它有一个include子目录,extension-template-c-main/duckdb_capi下也有头文件。
所以按照如下编写命令行,编译add_numbers.c通过
/par/extension-template-c-main/src# gcc -c add_numbers.c -I include -I ../duckdb_capi
再编译另一个文件capi_quack.c,报错了
/par/extension-template-c-main/src# gcc -c capi_quack.c -I include -I ../duckdb_capi
capi_quack.c:5:1: error: return type defaults to 'int' [-Wimplicit-int]5 | DUCKDB_EXTENSION_ENTRYPOINT(duckdb_connection connection, duckdb_extension_info info, struct duckdb_extension_access *access) {| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
好像是不认识DUCKDB_EXTENSION_ENTRYPOINT,到duckdb_capi/duckdb_extension.h中查找,发现这么一句, 后面跟着DUCKDB_EXTENSION_ENTRYPOINT宏定义
// Note: the DUCKDB_EXTENSION_ENTRYPOINT macro requires DUCKDB_EXTENSION_NAME to be set.#ifdef DUCKDB_EXTENSION_NAME// Main entrypoint: opens (and closes) a connection automatically for the extension to register its functionality
// through
#define DUCKDB_EXTENSION_ENTRYPOINT
...
那就好办了,在capi_quack.c开头添加
#define DUCKDB_EXTENSION_NAME add
一行
重新执行/par/extension-template-c-main/src# gcc -c capi_quack.c -I include -I ../duckdb_capi
不报错了。
按照通常编译动态库的命令语法,把两个c文件的内容编译到libtest.so
/par/extension-template-c-main/src# gcc -fPIC -shared -o libtest.so *.c -I include -I ../duckdb_capi
查看libtest.so中的导出函数,有一个add_init_c_api,就是我们的插件名add打头的。
/par/extension-template-c-main/src# nm -D libtest.so
0000000000001371 T RegisterAddNumbersFunctionw _ITM_deregisterTMCloneTablew _ITM_registerTMCloneTablew __cxa_finalize@GLIBC_2.2.5w __gmon_start__
000000000000149a T add_init_c_api
0000000000004040 B duckdb_ext_api
然后用extension-ci-tools/scripts中的append_extension_metadata.py添加元数据,因为文件名太长,我把它改名为appendmetadata.py,复制到/par目录。
/par/extension-template-c-main/src# python3 ../../appendmetadata.py -l libtest.so -n add -dv v1.2.0 --duckdb-platform linux_amd64 --extension-version 0.1
Creating extension binary:- Input file: libtest.so- Output file: add.duckdb_extension- Metadata:- FIELD8 (unused) = EMPTY- FIELD7 (unused) = EMPTY- FIELD6 (unused) = EMPTY- FIELD5 (abi_type) = C_STRUCT- FIELD4 (extension_version) = 0.1- FIELD3 (duckdb_version) = v1.2.0- FIELD2 (duckdb_platform) = linux_amd64- FIELD1 (header signature) = 4 (special value to identify a duckdb extension)
然后用-unsigned选项打开duckdb140 CLI,加载插件成功,文件名叫add_numbers.c,而函数名却叫multiply_numbers_together,从执行结果看,确实是相乘而不是相加,而且只有2个参数,多了报错。
/par/extension-template-c-main/src# /par/duckdb140 -unsigned
DuckDB v1.4.0 (Andium) b8a06e4a22
Enter ".help" for usage hints.
D load '/par/extension-template-c-main/src/add.duckdb_extension';
D select multiply_numbers_together(1,2);
┌─────────────────────────────────┐
│ multiply_numbers_together(1, 2) │
│ int64 │
├─────────────────────────────────┤
│ 2 │
└─────────────────────────────────┘
D select multiply_numbers_together(1,2,4,8);
Binder Error:
No function matches the given name and argument types 'multiply_numbers_together(INTEGER_LITERAL, INTEGER_LITERAL, INTEGER_LITERAL, INTEGER_LITERAL)'. You might need to add explicit type casts.Candidate functions:multiply_numbers_together(BIGINT, BIGINT) -> BIGINTLINE 1: select multiply_numbers_together(1,2,4,8);^
D with t as(select 3 a,7 b)select multiply_numbers_together(a,b) from t;
┌─────────────────────────────────┐
│ multiply_numbers_together(a, b) │
│ int64 │
├─────────────────────────────────┤
│ 21 │
└─────────────────────────────────┘