测试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空目录下。

首先尝试页面介绍的正规做法

bash 复制代码
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-venv

You may need to use sudo with that command.  After installing the python3-venv
package, recreate your virtual environment

按照提示安装python3.11-venv

bash 复制代码
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) ...

再次

bash 复制代码
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 main
    import duckdb
ModuleNotFoundError: No module named 'duckdb'

我只是要编译一个c插件,还要装python的duckdb模块, 太复杂了,放弃了。

看到extension-template-c-main目录下有个CMakeLists.txt,想到用cmake,

bash 复制代码
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通过

bash 复制代码
/par/extension-template-c-main/src# gcc -c add_numbers.c -I include -I ../duckdb_capi

再编译另一个文件capi_quack.c,报错了

bash 复制代码
/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宏定义

c 复制代码
// 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开头添加

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

bash 复制代码
/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打头的。

bash 复制代码
/par/extension-template-c-main/src# nm -D libtest.so
0000000000001371 T RegisterAddNumbersFunction
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w __cxa_finalize@GLIBC_2.2.5
                 w __gmon_start__
000000000000149a T add_init_c_api
0000000000004040 B duckdb_ext_api

然后用extension-ci-tools/scripts中的append_extension_metadata.py添加元数据,因为文件名太长,我把它改名为appendmetadata.py,复制到/par目录。

bash 复制代码
/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个参数,多了报错。

bash 复制代码
/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) -> BIGINT


LINE 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                │
└─────────────────────────────────┘
相关推荐
李广坤15 小时前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
祈安_20 小时前
C语言内存函数
c语言·后端
爱可生开源社区2 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1772 天前
《从零搭建NestJS项目》
数据库·typescript
郑州光合科技余经理2 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
feifeigo1232 天前
matlab画图工具
开发语言·matlab
加号32 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏2 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
dustcell.2 天前
haproxy七层代理
java·开发语言·前端
norlan_jame2 天前
C-PHY与D-PHY差异
c语言·开发语言