We have already written an initial article about DuckDB that explains initial concepts, installation and first steps. For more information, access the link:
In this article, we will see how to connect to DuckDB using the API with C++
The DuckDB API for C++ is not yet stable, on the API page itself there is this warning:
DuckDB's C++ API is internal. It is not guaranteed to be stable and can change without notice. If you would like to build an application on DuckDB, we recommend using the C API.
That’s why they recommend that you use the C API which works perfectly. To do this, just access the page: https://duckdb.org/docs/installation/ and choose the data according to your system. In my case, I chose:
Then just click on the .zip
that will be made available and download it, or download it with wget:
wget -q https://github.com/duckdb/duckdb/releases/download/v1.3.0/libduckdb-linux-amd64.zip
Unzip:
unzip libduckdb-linux-amd64.zip -d libduckdb-linux-amd64
Create a database and table, example: duckdb terminalroot.db
CREATE TABLE terminalroot (id INTEGER, name STRING);
INSERT INTO terminalroot VALUES(1, 'Marcos Oliveira');
INSERT INTO terminalroot VALUES(2, 'Mark Raasveldt');
INSERT INTO terminalroot VALUES(3, 'Hannes Muhleisen');
SELECT * FROM terminalroot;
.exit
Go into the directory you unzipped and create some basic code: cd libduckdb-linux-amd64/ && vim main.cpp
#include "duckdb.h"
#include <iostream>
int main(){
duckdb_database db;
duckdb_connection con;
duckdb_result result;
if(duckdb_open("terminalroot.db", &db) == DuckDBError){
std::cerr << "Error opening database\n";
return 1;
}
if(duckdb_connect(db, &con) == DuckDBError){
std::cerr << "Error connecting to database\n";
return 1; }
if(duckdb_query(con, "SELECT * FROM terminalroot;", &result) == DuckDBError){
std::cerr << "Error executing SELECT\n";
duckdb_disconnect(&con);
duckdb_close(&db);
return 1;
}
for(idx_t row = 0; row <= result.deprecated_column_count; row++){
int id = duckdb_value_int32(&result, 0, row);
const char* name = duckdb_value_varchar(&result, 1, row);
std::cout << id << " | " << name << '\n';
duckdb_free((void*)name); // free varchar memory
}
duckdb_destroy_result(&result);
duckdb_disconnect(&con);
duckdb_close(&db);
}
Compile and run:
g++ main.cpp libduckdb.so
LD_LIBRARY_PATH=. ./a.out
Probable output:
1 | Marcos Oliveira
2 | Mark Raasveldt
3 | Hannes Muhleisen
If you want to install on your system and compile with the -lduckdb
flag, run the commands below:
.h
to include
:sudo mkdir -p /usr/local/include/duckdb
sudo cp duckdb.h /usr/local/include/duckdb/
lib
And update the system’s shared library cache.
sudo cp libduckdb.so /usr/local/lib/
sudo ldconfig
After that, just test with the flag and you don’t even need to be in the folder with the downloaded files or use the environment variable:LD_LIBRARY_PATH
But you need
terminalroot.db
, if you put the absolute path, e.g.:"/home/$USER/.db/terminalroot.db"
your binary will run regardless of where you are in the system!
g++ main.cpp -lduckdb
./a.out
If you want to create .pc
for pkg-config
, expand the procedure below:
/usr/local/lib/pkgconfig/duckdb.pc
with this content:prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: DuckDB
Description: DuckDB embedded database
Version: 1.2.1
Libs: -L${libdir} -lduckdb
Cflags: -I${includedir}/duckdb
Save with:
sudo mkdir -p /usr/local/lib/pkgconfig
sudo vim /usr/local/lib/pkgconfig/duckdb.pc
# paste the above content
Refresh the cache:
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH
I tried the static library libduckdb_static.a
, but had problems, but if you prefer, try:
g++ main.cpp libduckdb_static.a -I. -ldl -pthread -lm -lz -static-libstdc++ -static-libgcc
If you also have problems, check for missing dependencies:
nm libduckdb_static.a | grep " U "
(
"U"
= undefined symbol)
Or use ldd ./a.out
to see if there are still dynamic libs hanging.
In my case none of these steps worked, but see if they apply to you too.
.hpp
: https://stackoverflow.com/questions/71782764/how-to-add-duckdb-library-in-c-program