From ef648cfe380e42f4f12fde363cd3afab88dd8512 Mon Sep 17 00:00:00 2001 From: Sunli Date: Wed, 26 Aug 2026 10:22:26 +0800 Subject: [PATCH] fix(cpp): build and repair asset::AssetContext MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `longbridge.hpp` has always included `asset_context.hpp`, so C++ users could see `asset::AssetContext` — but `cpp/src/asset_context.cpp` was never listed in `cpp/CMakeLists.txt`, so the class was declared and then failed to link. It had never compiled either; three separate problems had accumulated behind the missing build entry. **`lb_statement_item_t` was not in the generated header.** `CStatementItem` is only reachable through the `void*` async-result pointer, so cbindgen never emitted it and no caller could read what `lb_asset_context_statements` returns. Exported it the same way the GridContext payloads are. `CAssetContext` was also missing from the rename map — every other context type was mapped, so the header exposed the raw Rust name (`const struct CAssetContext *lb_asset_context_new(…)`) while the C++ side forward-declares `lb_asset_context_t`. **`asset_context.cpp` did not include the C header.** Every other context source includes `longbridge.h`; this one included only its own `.hpp`, which forward-declares `lb_asset_context_t` as an opaque struct and nothing else — so `lb_asset_context_retain` and friends were undeclared. **`statement_download_url` decoded the wrong shape.** It read `res->data` as a `lb_statement_download_url_response_t*` and took `->url`. No such type exists anywhere in the C layer: `lb_asset_context_download_url` resolves a `CString`, so the callback receives the URL as a bare `const char*` — the same convention as `QuoteContext::quote_level`. Verified against a live environment: `statements` returns the same empty list the Rust core returns for the same account, and the symbols are present in `liblongbridge_cpp.so`. `statement_download_url` is compile- and link-checked only — the test account has no statement to supply a `file_key`. --- CHANGELOG.md | 5 +++++ c/cbindgen.toml | 4 ++++ c/csrc/include/longbridge.h | 26 ++++++++++++++++++++------ cpp/CMakeLists.txt | 1 + cpp/src/asset_context.cpp | 4 ++-- 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1885701d79..a8f59fae4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- **C++ SDK:** `asset::AssetContext` (`statements` / `statement_download_url`) is now actually built and usable. `longbridge.hpp` has always included `asset_context.hpp`, but `cpp/src/asset_context.cpp` was never listed in `cpp/CMakeLists.txt`, so the class was declared to users and then failed to link. It had also never compiled: it included neither `longbridge.h` nor the C declarations, and `statement_download_url` read `res->data` as a `lb_statement_download_url_response_t*` — a type that does not exist anywhere in the C layer, which delivers the URL as a bare `const char*` (the same convention as `QuoteContext::quote_level`). Fixed the include and the callback, and added the file to the build +- **C SDK:** export `lb_statement_item_t` from `longbridge.h`. `CStatementItem` is only reachable through the `void*` async-result pointer, so cbindgen did not emit it and no C or C++ caller could read what `lb_asset_context_statements` returns. Also added the missing `CAssetContext` → `lb_asset_context_t` entry to the cbindgen rename map: every other context type was mapped, so the header exposed the raw Rust name (`const struct CAssetContext *lb_asset_context_new(...)`) while the C++ side forward-declared `lb_asset_context_t` + ### Added - **Rust:** `Signal.status` is now a `SignalStatus` enum (pending / active / deleted / ai-failed / filtered-by-manual / ai-submit-failed), `SignalsResponse.total` is `i32` to match the wire contract, and the `risk_level` / `display_control` fields were dropped — neither is part of the API contract nor served in production diff --git a/c/cbindgen.toml b/c/cbindgen.toml index 5f0f304a5d..0e20bf6f83 100644 --- a/c/cbindgen.toml +++ b/c/cbindgen.toml @@ -167,6 +167,8 @@ cpp_compat = true "CCalendarContext" = "lb_calendar_context_t" "CPortfolioContext" = "lb_portfolio_context_t" "CMarketContext" = "lb_market_context_t" +"CAssetContext" = "lb_asset_context_t" +"CStatementItem" = "lb_statement_item_t" # MarketContext types "CMarketTimeItem" = "lb_market_time_item_t" "CMarketStatusResponse" = "lb_market_status_response_t" @@ -428,6 +430,8 @@ include = [ "CWatchlistSecurity", "CMarginRatio", "COrderDetail", + # AssetContext: statements (reachable only via void* async data pointer) + "CStatementItem", # GridContext: grid trading (reachable only via void* async data pointer) "CSubmitGridOrderResponse", "CGridOrder", "CGridOrderSubOrder", "CGridOrderHistory", "CGridOrderDetail", diff --git a/c/csrc/include/longbridge.h b/c/csrc/include/longbridge.h index 3bb25d2f52..b67fb3adef 100644 --- a/c/csrc/include/longbridge.h +++ b/c/csrc/include/longbridge.h @@ -1853,7 +1853,7 @@ typedef struct lb_alert_context_t lb_alert_context_t; /** * Asset context */ -typedef struct CAssetContext CAssetContext; +typedef struct lb_asset_context_t lb_asset_context_t; typedef struct lb_calendar_context_t lb_calendar_context_t; @@ -6065,6 +6065,20 @@ typedef struct lb_order_detail_t { struct CMultiLegInfo multi_leg; } lb_order_detail_t; +/** + * Statement item + */ +typedef struct lb_statement_item_t { + /** + * Statement date (integer, e.g. 20250301) + */ + int32_t dt; + /** + * File key + */ + const char *file_key; +} lb_statement_item_t; + /** * Response for submit grid trading order request */ @@ -11862,17 +11876,17 @@ void lb_alert_context_delete(const struct lb_alert_context_t *ctx, * @param config Config object * @return A new asset context */ -const struct CAssetContext *lb_asset_context_new(const struct lb_config_t *config); +const struct lb_asset_context_t *lb_asset_context_new(const struct lb_config_t *config); /** * Retain the asset context (increment reference count) */ -void lb_asset_context_retain(const struct CAssetContext *ctx); +void lb_asset_context_retain(const struct lb_asset_context_t *ctx); /** * Release the asset context (decrement reference count) */ -void lb_asset_context_release(const struct CAssetContext *ctx); +void lb_asset_context_release(const struct lb_asset_context_t *ctx); /** * Get statement data list @@ -11884,7 +11898,7 @@ void lb_asset_context_release(const struct CAssetContext *ctx); * @param callback Async callback * @param userdata User data passed to the callback */ -void lb_asset_context_statements(const struct CAssetContext *ctx, +void lb_asset_context_statements(const struct lb_asset_context_t *ctx, int32_t statement_type, int32_t start_date, int32_t limit, @@ -11899,7 +11913,7 @@ void lb_asset_context_statements(const struct CAssetContext *ctx, * @param callback Async callback * @param userdata User data passed to the callback */ -void lb_asset_context_download_url(const struct CAssetContext *ctx, +void lb_asset_context_download_url(const struct lb_asset_context_t *ctx, const char *file_key, lb_async_callback_t callback, void *userdata); diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 89c86bf445..89cfa535de 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -6,6 +6,7 @@ set(SOURCES src/decimal.cpp src/agent_context.cpp src/alert_context.cpp + src/asset_context.cpp src/dca_context.cpp src/sharelist_context.cpp src/calendar_context.cpp diff --git a/cpp/src/asset_context.cpp b/cpp/src/asset_context.cpp index bb7a154400..16b29b6e93 100644 --- a/cpp/src/asset_context.cpp +++ b/cpp/src/asset_context.cpp @@ -1,4 +1,5 @@ #include "asset_context.hpp" +#include "longbridge.h" #include #include @@ -122,9 +123,8 @@ AssetContext::statement_download_url( Status status(res->error); if (status) { - auto resp = (const lb_statement_download_url_response_t*)res->data; StatementDownloadUrlResponse result; - result.url = resp->url; + result.url = (const char*)res->data; (*callback_ptr)( AsyncResult(