Skip to content

Commit

Permalink
add example
Browse files Browse the repository at this point in the history
  • Loading branch information
mlin committed Jan 23, 2021
1 parent 4590c8e commit 8f42f71
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 0 deletions.
1 change: 1 addition & 0 deletions examples/example3_ext/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/
24 changes: 24 additions & 0 deletions examples/example3_ext/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Example building a SQLite3 loadable extension that uses SQLiteCpp internally
cmake_minimum_required(VERSION 3.1) # for "CMAKE_CXX_STANDARD" version
project(SQLiteCpp_ExampleExtension VERSION 1.0)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# KEY OPTION HERE: builds SQLiteCpp for use within the implementation of a loadable extension
set(SQLITECPP_IN_EXTENSION ON CACHE BOOL "" FORCE)

set(SQLITECPP_RUN_CPPCHECK OFF CACHE BOOL "" FORCE)
set(SQLITECPP_RUN_CPPLINT OFF CACHE BOOL "" FORCE)
set(SQLITECPP_USE_STATIC_RUNTIME OFF CACHE BOOL "" FORCE)
set(SQLITECPP_USE_STATIC_RUNTIME OFF CACHE BOOL "" FORCE)
add_subdirectory(../.. SQLiteCpp) # out-of-source build requires explicit subdir name for compilation artifacts

add_library(example SHARED src/example_extension.cpp)
target_link_libraries(example SQLiteCpp)

# Compile driver program that'll load the extension. It links sqlite3 statically, so our extension library
# mustn't itself link sqlite3, either statically or dynamically (that's one thing accomplished by
# SQLITECPP_IN_EXTENSION)
add_executable(example_driver src/main.cpp)
target_link_libraries(example_driver -static sqlite3 dl pthread)
16 changes: 16 additions & 0 deletions examples/example3_ext/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
This example demonstrates how to use SQLiteCpp *within the implementation* of a
[SQLite3 loadable extension](https://sqlite.org/loadext.html). Change into this directory and

```
cmake -B build .
cmake --build build
build/example_driver $(pwd)/build/libexample.so
```

*(replace .so with .dylib or .dll if appropriate)*

This should print `it works 42`. Here the `example_driver` program links SQLite3 *statically*, so
it's important to ensure that SQLiteCpp inside the extension will use that "copy" of SQLite3 rather
than trying to dynamically link another one. See [CMakeLists.txt](CMakeLists.txt) for the key CMake
option that ensures this, and [src/example_extension.cpp](src/example_extension.cpp) for some
necessary boilerplate.
31 changes: 31 additions & 0 deletions examples/example3_ext/src/example_extension.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Example using SQLiteCpp within the implementation of a SQLite3 run-time loadable extension
// SEE: https://sqlite.org/loadext.html
#include <sqlite3ext.h>
// When SQLiteCpp is built with option SQLITECPP_IN_EXTENSION=ON, its compiled objects will expect
// to find an extern "C" symbol declared by the following macro in the extension implementation.
extern "C" {
SQLITE_EXTENSION_INIT1
}
#include <SQLiteCpp/SQLiteCpp.h>
#include <iostream>

extern "C" int sqlite3_example_init(sqlite3 *rawDb, char **pzErrMsg,
const sqlite3_api_routines *pApi) {
SQLITE_EXTENSION_INIT2(pApi);

try {
// temporarily wrap rawDb as a SQLite::Database so we can use SQLiteCpp's conveniences
SQLite::Database db(rawDb);
SQLite::Statement stmt(db, "SELECT 'it works ' || ?");
stmt.bind(1, 42);
if (stmt.executeStep()) {
std::cout << stmt.getColumn(0).getString() << std::endl;
}
// In a real extension we'd now register custom functions, virtual tables, or VFS objects,
// any of which might also want to use SQLiteCpp wrappers for the raw connection.
return SQLITE_OK;
} catch (SQLite::Exception& exn) {
std::cerr << exn.getErrorStr() << std::endl;
return exn.getErrorCode();
}
}
26 changes: 26 additions & 0 deletions examples/example3_ext/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// driver program to load a SQLite3 extension

#include <sqlite3.h>
#include <iostream>

int main(int argc, char **argv) {
if (argc < 2) {
std::cerr << "Usage: example_driver EXTENSION_ABSOLUTE_PATH" << std::endl;
return -1;
}
sqlite3 *db;
if (sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, nullptr) != SQLITE_OK) {
std::cerr << "sqlite3_open_v2() failed" << std::endl;
return -1;
}
char *zErrMsg = nullptr;
if (sqlite3_load_extension(db, argv[1], nullptr, &zErrMsg) != SQLITE_OK) {
std::cerr << "sqlite3_load_extension() failed";
if (zErrMsg) {
std::cerr << ": " << zErrMsg << std::endl;
}
std::cerr << std::endl;
return -1;
}
return 0;
}

0 comments on commit 8f42f71

Please sign in to comment.