Skip to content

Commit 8f42f71

Browse files
committed
add example
1 parent 4590c8e commit 8f42f71

File tree

5 files changed

+98
-0
lines changed

5 files changed

+98
-0
lines changed

examples/example3_ext/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
build/

examples/example3_ext/CMakeLists.txt

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Example building a SQLite3 loadable extension that uses SQLiteCpp internally
2+
cmake_minimum_required(VERSION 3.1) # for "CMAKE_CXX_STANDARD" version
3+
project(SQLiteCpp_ExampleExtension VERSION 1.0)
4+
5+
set(CMAKE_CXX_STANDARD 11)
6+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
7+
8+
# KEY OPTION HERE: builds SQLiteCpp for use within the implementation of a loadable extension
9+
set(SQLITECPP_IN_EXTENSION ON CACHE BOOL "" FORCE)
10+
11+
set(SQLITECPP_RUN_CPPCHECK OFF CACHE BOOL "" FORCE)
12+
set(SQLITECPP_RUN_CPPLINT OFF CACHE BOOL "" FORCE)
13+
set(SQLITECPP_USE_STATIC_RUNTIME OFF CACHE BOOL "" FORCE)
14+
set(SQLITECPP_USE_STATIC_RUNTIME OFF CACHE BOOL "" FORCE)
15+
add_subdirectory(../.. SQLiteCpp) # out-of-source build requires explicit subdir name for compilation artifacts
16+
17+
add_library(example SHARED src/example_extension.cpp)
18+
target_link_libraries(example SQLiteCpp)
19+
20+
# Compile driver program that'll load the extension. It links sqlite3 statically, so our extension library
21+
# mustn't itself link sqlite3, either statically or dynamically (that's one thing accomplished by
22+
# SQLITECPP_IN_EXTENSION)
23+
add_executable(example_driver src/main.cpp)
24+
target_link_libraries(example_driver -static sqlite3 dl pthread)

examples/example3_ext/README.md

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
This example demonstrates how to use SQLiteCpp *within the implementation* of a
2+
[SQLite3 loadable extension](https://sqlite.org/loadext.html). Change into this directory and
3+
4+
```
5+
cmake -B build .
6+
cmake --build build
7+
build/example_driver $(pwd)/build/libexample.so
8+
```
9+
10+
*(replace .so with .dylib or .dll if appropriate)*
11+
12+
This should print `it works 42`. Here the `example_driver` program links SQLite3 *statically*, so
13+
it's important to ensure that SQLiteCpp inside the extension will use that "copy" of SQLite3 rather
14+
than trying to dynamically link another one. See [CMakeLists.txt](CMakeLists.txt) for the key CMake
15+
option that ensures this, and [src/example_extension.cpp](src/example_extension.cpp) for some
16+
necessary boilerplate.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Example using SQLiteCpp within the implementation of a SQLite3 run-time loadable extension
2+
// SEE: https://sqlite.org/loadext.html
3+
#include <sqlite3ext.h>
4+
// When SQLiteCpp is built with option SQLITECPP_IN_EXTENSION=ON, its compiled objects will expect
5+
// to find an extern "C" symbol declared by the following macro in the extension implementation.
6+
extern "C" {
7+
SQLITE_EXTENSION_INIT1
8+
}
9+
#include <SQLiteCpp/SQLiteCpp.h>
10+
#include <iostream>
11+
12+
extern "C" int sqlite3_example_init(sqlite3 *rawDb, char **pzErrMsg,
13+
const sqlite3_api_routines *pApi) {
14+
SQLITE_EXTENSION_INIT2(pApi);
15+
16+
try {
17+
// temporarily wrap rawDb as a SQLite::Database so we can use SQLiteCpp's conveniences
18+
SQLite::Database db(rawDb);
19+
SQLite::Statement stmt(db, "SELECT 'it works ' || ?");
20+
stmt.bind(1, 42);
21+
if (stmt.executeStep()) {
22+
std::cout << stmt.getColumn(0).getString() << std::endl;
23+
}
24+
// In a real extension we'd now register custom functions, virtual tables, or VFS objects,
25+
// any of which might also want to use SQLiteCpp wrappers for the raw connection.
26+
return SQLITE_OK;
27+
} catch (SQLite::Exception& exn) {
28+
std::cerr << exn.getErrorStr() << std::endl;
29+
return exn.getErrorCode();
30+
}
31+
}

examples/example3_ext/src/main.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// driver program to load a SQLite3 extension
2+
3+
#include <sqlite3.h>
4+
#include <iostream>
5+
6+
int main(int argc, char **argv) {
7+
if (argc < 2) {
8+
std::cerr << "Usage: example_driver EXTENSION_ABSOLUTE_PATH" << std::endl;
9+
return -1;
10+
}
11+
sqlite3 *db;
12+
if (sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, nullptr) != SQLITE_OK) {
13+
std::cerr << "sqlite3_open_v2() failed" << std::endl;
14+
return -1;
15+
}
16+
char *zErrMsg = nullptr;
17+
if (sqlite3_load_extension(db, argv[1], nullptr, &zErrMsg) != SQLITE_OK) {
18+
std::cerr << "sqlite3_load_extension() failed";
19+
if (zErrMsg) {
20+
std::cerr << ": " << zErrMsg << std::endl;
21+
}
22+
std::cerr << std::endl;
23+
return -1;
24+
}
25+
return 0;
26+
}

0 commit comments

Comments
 (0)