-
Notifications
You must be signed in to change notification settings - Fork 3
feat: C++ bindings support #41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -71,4 +71,6 @@ src/rust/fcb_core/tests/data/*.json | |
| flamegraph* | ||
| .roo | ||
| .serena/ | ||
| *.so | ||
| *.so | ||
|
|
||
| build/ | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,83 @@ | ||||||||||||||||||||||||||||||||||
| cmake_minimum_required(VERSION 3.16) | ||||||||||||||||||||||||||||||||||
| project(fcb_cpp VERSION 0.1.0 LANGUAGES CXX) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| set(CMAKE_CXX_STANDARD 17) | ||||||||||||||||||||||||||||||||||
| set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Find cxxbridge CLI tool | ||||||||||||||||||||||||||||||||||
| find_program(CXXBRIDGE cxxbridge) | ||||||||||||||||||||||||||||||||||
| if(NOT CXXBRIDGE) | ||||||||||||||||||||||||||||||||||
| message(STATUS "cxxbridge not found, installing via cargo...") | ||||||||||||||||||||||||||||||||||
| execute_process( | ||||||||||||||||||||||||||||||||||
| COMMAND cargo install cxxbridge-cmd | ||||||||||||||||||||||||||||||||||
| RESULT_VARIABLE CXXBRIDGE_INSTALL_RESULT | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
| find_program(CXXBRIDGE cxxbridge REQUIRED) | ||||||||||||||||||||||||||||||||||
| endif() | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Configuration | ||||||||||||||||||||||||||||||||||
| set(RUST_LIB_DIR ${CMAKE_SOURCE_DIR}/../rust) | ||||||||||||||||||||||||||||||||||
| set(GENERATED_DIR ${CMAKE_BINARY_DIR}/generated) | ||||||||||||||||||||||||||||||||||
| file(MAKE_DIRECTORY ${GENERATED_DIR}) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Build Rust static library | ||||||||||||||||||||||||||||||||||
| add_custom_command( | ||||||||||||||||||||||||||||||||||
| OUTPUT ${RUST_LIB_DIR}/target/release/libfcb_cpp.a | ||||||||||||||||||||||||||||||||||
| COMMAND cargo build --release -p fcb_cpp | ||||||||||||||||||||||||||||||||||
| WORKING_DIRECTORY ${RUST_LIB_DIR} | ||||||||||||||||||||||||||||||||||
| DEPENDS ${RUST_LIB_DIR}/fcb_cpp/src/lib.rs | ||||||||||||||||||||||||||||||||||
| DEPENDS ${RUST_LIB_DIR}/fcb_cpp/src/reader.rs | ||||||||||||||||||||||||||||||||||
| DEPENDS ${RUST_LIB_DIR}/fcb_cpp/src/writer.rs | ||||||||||||||||||||||||||||||||||
| COMMENT "Building Rust fcb_cpp library" | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| add_custom_target(rust_library DEPENDS ${RUST_LIB_DIR}/target/release/libfcb_cpp.a) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Generate C++ bridge code | ||||||||||||||||||||||||||||||||||
| add_custom_command( | ||||||||||||||||||||||||||||||||||
| OUTPUT ${GENERATED_DIR}/lib.rs.h | ||||||||||||||||||||||||||||||||||
| COMMAND ${CXXBRIDGE} ${RUST_LIB_DIR}/fcb_cpp/src/lib.rs --header > ${GENERATED_DIR}/lib.rs.h | ||||||||||||||||||||||||||||||||||
| DEPENDS ${RUST_LIB_DIR}/fcb_cpp/src/lib.rs | ||||||||||||||||||||||||||||||||||
| COMMENT "Generating C++ header from CXX bridge" | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| add_custom_command( | ||||||||||||||||||||||||||||||||||
| OUTPUT ${GENERATED_DIR}/lib.rs.cc | ||||||||||||||||||||||||||||||||||
| COMMAND ${CXXBRIDGE} ${RUST_LIB_DIR}/fcb_cpp/src/lib.rs > ${GENERATED_DIR}/lib.rs.cc | ||||||||||||||||||||||||||||||||||
| DEPENDS ${RUST_LIB_DIR}/fcb_cpp/src/lib.rs | ||||||||||||||||||||||||||||||||||
| COMMENT "Generating C++ source from CXX bridge" | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Create fcb library | ||||||||||||||||||||||||||||||||||
| add_library(fcb STATIC | ||||||||||||||||||||||||||||||||||
| ${GENERATED_DIR}/lib.rs.cc | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+44
to
+54
|
||||||||||||||||||||||||||||||||||
| add_custom_command( | |
| OUTPUT ${GENERATED_DIR}/lib.rs.cc | |
| COMMAND ${CXXBRIDGE} ${RUST_LIB_DIR}/fcb_cpp/src/lib.rs > ${GENERATED_DIR}/lib.rs.cc | |
| DEPENDS ${RUST_LIB_DIR}/fcb_cpp/src/lib.rs | |
| COMMENT "Generating C++ source from CXX bridge" | |
| ) | |
| # Create fcb library | |
| add_library(fcb STATIC | |
| ${GENERATED_DIR}/lib.rs.cc | |
| ) | |
| # Note: The CXX bridge C++ source is compiled by the Rust build (build.rs via cxx_build), | |
| # so we only generate the header here to avoid duplicate symbol definitions. | |
| # Create fcb library (acts as a wrapper around the Rust static library) | |
| add_library(fcb STATIC) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| #include "lib.rs.h" | ||
| #include <iostream> | ||
| #include <stdexcept> | ||
| #include <string> | ||
|
|
||
| int main(int argc, char *argv[]) { | ||
| if (argc < 2) { | ||
| std::cerr << "Usage: " << argv[0] << " <fcb_file>" << std::endl; | ||
| return 1; | ||
| } | ||
|
|
||
| std::string path = argv[1]; | ||
|
|
||
| try { | ||
| // Open FCB file | ||
| auto reader = fcb::fcb_reader_open(path); | ||
|
|
||
| // Get metadata | ||
| auto meta = fcb::fcb_reader_metadata(*reader); | ||
| std::cout << "=== FCB File Metadata ===" << std::endl; | ||
| std::cout << "Version: " << static_cast<int>(meta.version) << std::endl; | ||
| std::cout << "Features count: " << meta.features_count << std::endl; | ||
| std::cout << "Has spatial index: " | ||
| << (meta.has_spatial_index ? "yes" : "no") << std::endl; | ||
| std::cout << "Has attribute index: " | ||
| << (meta.has_attribute_index ? "yes" : "no") << std::endl; | ||
| std::cout << std::endl; | ||
|
|
||
| // Select all features | ||
| auto iter = fcb::fcb_reader_select_all(std::move(reader)); | ||
|
|
||
| std::cout << "=== Features ===" << std::endl; | ||
| size_t count = 0; | ||
| while (fcb::fcb_iterator_next(*iter)) { | ||
| auto feature = fcb::fcb_iterator_current(*iter); | ||
| std::cout << "Feature " << count << ": ID=" << std::string(feature.id) | ||
| << std::endl; | ||
|
|
||
| // Print first 200 chars of JSON | ||
| std::string json = std::string(feature.json); | ||
| if (json.length() > 200) { | ||
| json = json.substr(0, 200) + "..."; | ||
| } | ||
| std::cout << " JSON: " << json << std::endl; | ||
|
|
||
| count++; | ||
| if (count >= 5) { | ||
| std::cout << " ... (showing first 5 features)" << std::endl; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| std::cout << std::endl; | ||
| std::cout << "Total features iterated: " << count << std::endl; | ||
|
|
||
| } catch (const std::exception &e) { | ||
| std::cerr << "Error: " << e.what() << std::endl; | ||
| return 1; | ||
| } | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| [package] | ||
| name = "fcb_cpp" | ||
| version = "0.1.0" | ||
| edition = "2021" | ||
| authors = ["Hidemichi Baba <baba.papa1120.ba@gmail.com>"] | ||
| license = "MIT" | ||
| description = "C++ bindings for FlatCityBuf core library" | ||
|
|
||
| [lib] | ||
| crate-type = ["staticlib"] | ||
|
|
||
| [dependencies] | ||
| fcb_core = { workspace = true } | ||
| cxx = { workspace = true } | ||
| cjseq = { workspace = true } | ||
| serde_json = { workspace = true } | ||
|
|
||
| [build-dependencies] | ||
| cxx-build = { workspace = true } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This CMake script automatically installs and executes the
cxxbridge-cmdtool viacargo install cxxbridge-cmdwithout pinning a version or verifying integrity, which introduces a build-time supply-chain risk. An attacker who compromises the crate or crates.io could ship a maliciouscxxbridge-cmdthat runs in your build and generates backdoored bridge code compiled into production artifacts. To mitigate this, avoid auto-installation in the build, pincxxbridge-cmdto a specific trusted version or commit, and/or vendor or pre-generate the bridge code so that build steps do not fetch and execute mutable third-party tooling.