From 7c50f8d5d53ca10b19efc378f4a569630a8b089d Mon Sep 17 00:00:00 2001 From: qwe <186387150877@163.com> Date: Thu, 28 May 2026 00:24:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=86=B3=E5=AE=9A=E4=BD=BF=E7=94=A8=20CPP=20?= =?UTF-8?q?=E5=BA=93=E5=A4=84=E7=90=86=20xls=20=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go/go.mod | 15 ------ go/go.sum | 18 ------- go/main.go | 1 - lib_cpp/CMakeLists.txt | 24 +++++++++ lib_cpp/include/xlsx_reader.h | 28 ++++++++++ lib_cpp/src/xlsx_reader.cpp | 96 +++++++++++++++++++++++++++++++++++ 6 files changed, 148 insertions(+), 34 deletions(-) delete mode 100644 go/go.mod delete mode 100644 go/go.sum delete mode 100644 go/main.go create mode 100644 lib_cpp/CMakeLists.txt create mode 100644 lib_cpp/include/xlsx_reader.h create mode 100644 lib_cpp/src/xlsx_reader.cpp diff --git a/go/go.mod b/go/go.mod deleted file mode 100644 index 3a0c026..0000000 --- a/go/go.mod +++ /dev/null @@ -1,15 +0,0 @@ -module xlsxUtils - -go 1.25.5 - -require ( - github.com/richardlehane/mscfb v1.0.6 // indirect - github.com/richardlehane/msoleps v1.0.6 // indirect - github.com/tiendc/go-deepcopy v1.7.2 // indirect - github.com/xuri/efp v0.0.1 // indirect - github.com/xuri/excelize/v2 v2.10.1 // indirect - github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 // indirect - golang.org/x/crypto v0.48.0 // indirect - golang.org/x/net v0.50.0 // indirect - golang.org/x/text v0.34.0 // indirect -) diff --git a/go/go.sum b/go/go.sum deleted file mode 100644 index 9b29b0f..0000000 --- a/go/go.sum +++ /dev/null @@ -1,18 +0,0 @@ -github.com/richardlehane/mscfb v1.0.6 h1:eN3bvvZCp00bs7Zf52bxNwAx5lJDBK1tCuH19qq5aC8= -github.com/richardlehane/mscfb v1.0.6/go.mod h1:pe0+IUIc0AHh0+teNzBlJCtSyZdFOGgV4ZK9bsoV+Jo= -github.com/richardlehane/msoleps v1.0.6 h1:9BvkpjvD+iUBalUY4esMwv6uBkfOip/Lzvd93jvR9gg= -github.com/richardlehane/msoleps v1.0.6/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= -github.com/tiendc/go-deepcopy v1.7.2 h1:Ut2yYR7W9tWjTQitganoIue4UGxZwCcJy3orjrrIj44= -github.com/tiendc/go-deepcopy v1.7.2/go.mod h1:4bKjNC2r7boYOkD2IOuZpYjmlDdzjbpTRyCx+goBCJQ= -github.com/xuri/efp v0.0.1 h1:fws5Rv3myXyYni8uwj2qKjVaRP30PdjeYe2Y6FDsCL8= -github.com/xuri/efp v0.0.1/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI= -github.com/xuri/excelize/v2 v2.10.1 h1:V62UlqopMqha3kOpnlHy2CcRVw1V8E63jFoWUmMzxN0= -github.com/xuri/excelize/v2 v2.10.1/go.mod h1:iG5tARpgaEeIhTqt3/fgXCGoBRt4hNXgCp3tfXKoOIc= -github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 h1:+C0TIdyyYmzadGaL/HBLbf3WdLgC29pgyhTjAT/0nuE= -github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= -golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= -golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= -golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= -golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= diff --git a/go/main.go b/go/main.go deleted file mode 100644 index 06ab7d0..0000000 --- a/go/main.go +++ /dev/null @@ -1 +0,0 @@ -package main diff --git a/lib_cpp/CMakeLists.txt b/lib_cpp/CMakeLists.txt new file mode 100644 index 0000000..4c175be --- /dev/null +++ b/lib_cpp/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.14) +project(xlsx_reader VERSION 1.0.0 LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +set(CMAKE_CXX_VISIBILITY_PRESET hidden) +set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) + +include(FetchContent) + +add_subdirectory(third_party/OpenXLSX) + +set(OPENXLSX_STATIC ON CACHE BOOL "Build OpenXLSX as static library") +FetchContent_MakeAvailable(OpenXLSX) + +add_library(xlsx_reader SHARED src/xlsx_reader.cpp) + +target_include_directories(xlsx_reader PUBLIC include) + +target_link_libraries(xlsx_reader PRIVATE OpenXLSX::OpenXLSX) + +target_compile_definitions(xlsx_reader PRIVATE XLSX_BUILD_SHARED) diff --git a/lib_cpp/include/xlsx_reader.h b/lib_cpp/include/xlsx_reader.h new file mode 100644 index 0000000..a3b760c --- /dev/null +++ b/lib_cpp/include/xlsx_reader.h @@ -0,0 +1,28 @@ +#ifndef XLSX_READER_H +#define XLSX_READER_H + +#if defined(_WIN32) + #if defined(XLSX_BUILD_SHARED) + #define XLSX_API __declspec(dllexport) + #else + #define XLSX_API __declspec(dllimport) + #endif +#elif defined(__GNUC__) || defined(__clang__) + #define XLSX_API __attribute__((visibility("default"))) +#else + #define XLSX_API +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +XLSX_API char* xlsx_read_first_sheet(const char* filepath); + +XLSX_API void xlsx_free_string(char* str); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib_cpp/src/xlsx_reader.cpp b/lib_cpp/src/xlsx_reader.cpp new file mode 100644 index 0000000..f3f340c --- /dev/null +++ b/lib_cpp/src/xlsx_reader.cpp @@ -0,0 +1,96 @@ +#include "xlsx_reader.h" + +#include + +#include +#include +#include + +static std::string jsonEscape(const std::string& s) { + std::string out; + out.reserve(s.size() + 2); + for (char c : s) { + switch (c) { + case '"': out += "\\\""; break; + case '\\': out += "\\\\"; break; + case '\n': out += "\\n"; break; + case '\t': out += "\\t"; break; + case '\r': out += "\\r"; break; + default: + if (static_cast(c) < 0x20) { + char buf[8]; + std::snprintf(buf, sizeof(buf), "\\u%04x", + static_cast(c)); + out += buf; + } else { + out += c; + } + } + } + return out; +} + +static std::string cellAsString(const OpenXLSX::XLCell& cell) { + using namespace OpenXLSX; + auto& val = cell.value(); + switch (val.type()) { + case XLValueType::Integer: + return std::to_string(val.get()); + case XLValueType::Float: + return std::to_string(val.get()); + case XLValueType::String: + return val.get(); + case XLValueType::Boolean: + return val.get() ? "true" : "false"; + case XLValueType::Empty: + default: + return {}; + } +} + +extern "C" XLSX_API char* xlsx_read_first_sheet(const char* filepath) { + if (!filepath) return nullptr; + + try { + OpenXLSX::XLDocument doc; + doc.open(filepath); + + auto wks = doc.workbook().worksheet(1); + + std::string json; + json += '['; + + bool firstRow = true; + for (auto& row : wks.rows()) { + if (!firstRow) json += ','; + json += '['; + + bool firstCell = true; + for (auto& cell : row.cells()) { + if (!firstCell) json += ','; + json += '"'; + json += jsonEscape(cellAsString(cell)); + json += '"'; + firstCell = false; + } + + json += ']'; + firstRow = false; + } + + json += ']'; + doc.close(); + + char* result = static_cast(std::malloc(json.size() + 1)); + if (result) { + std::memcpy(result, json.c_str(), json.size() + 1); + } + return result; + } catch (const std::exception&) { + return nullptr; + } +} + +extern "C" XLSX_API void xlsx_free_string(char* str) { + std::free(str); +}