C / FFI Office-бібліотека — швидкий старт
C API office_oxide — стабільне тонке ABI поверх Rust-ядра. Усі вищі прив’язки (Go, C#, Node.js native) викликають ті самі точки входу. Якщо у вашій екосистемі немає готового врапера, можна завжди лінкувати C-бібліотеку напряму.
Авторитетна поверхня знаходиться в include/office_oxide_c/office_oxide.h; цей гайд описує те саме API.
Встановлення
Варіант 1 — зібрати з Rust-джерел
git clone https://github.com/yfedoseev/office_oxide
cd office_oxide
cargo build --release --lib
Спільна бібліотека з’явиться в target/release/:
| OS | Файл |
|---|---|
| Linux | liboffice_oxide.so |
| macOS | liboffice_oxide.dylib |
| Windows | office_oxide.dll (+ .lib-імпорт) |
Заголовок — include/office_oxide_c/office_oxide.h.
Варіант 2 — встановити prebuilt
install -Dm644 include/office_oxide_c/office_oxide.h /usr/local/include/office_oxide.h
install -Dm755 target/release/liboffice_oxide.so /usr/local/lib/liboffice_oxide.so
Прочитати документ
#include <stdio.h>
#include <stdlib.h>
#include "office_oxide.h"
int main(void) {
int err = 0;
char *text = office_extract_text("report.docx", &err);
if (!text) {
fprintf(stderr, "office_oxide failed: code=%d\n", err);
return 1;
}
printf("%s\n", text);
office_oxide_free_string(text);
return 0;
}
Збірка та запуск:
cc quickstart.c -I/usr/local/include -L/usr/local/lib -loffice_oxide -o quickstart
LD_LIBRARY_PATH=/usr/local/lib ./quickstart
Базовий API
Інформація про бібліотеку
const char *version = office_oxide_version(); // "0.1.0" — не звільняти
const char *fmt = office_oxide_detect_format("f"); // "docx"/... або NULL
Document (read-only)
int err = 0;
OfficeDocumentHandle *doc = office_document_open("file.xlsx", &err);
if (!doc) { /* обробити err */ }
const char *fmt = office_document_format(doc); // "xlsx" — не звільняти
char *text = office_document_plain_text(doc, &err);
char *md = office_document_to_markdown(doc, &err);
char *html = office_document_to_html(doc, &err);
char *ir = office_document_to_ir_json(doc, &err);
if (office_document_save_as(doc, "file.docx", &err) != 0) { /* обробити err */ }
office_oxide_free_string(text);
office_oxide_free_string(md);
office_oxide_free_string(html);
office_oxide_free_string(ir);
office_document_free(doc);
Відкриття з in-memory буфера:
uint8_t *data = ...;
size_t len = ...;
OfficeDocumentHandle *doc =
office_document_open_from_bytes(data, len, "docx", &err);
format має бути одним із шести рядків: "docx" | "xlsx" | "pptx" | "doc" | "xls" | "ppt".
EditableDocument
Редагування зберігає дослівно всі незмінені OPC-частини. Лише DOCX, XLSX та PPTX.
int err = 0;
OfficeEditableHandle *ed = office_editable_open("template.docx", &err);
if (!ed) { /* обробити err */ }
int64_t n = office_editable_replace_text(ed, "{{name}}", "Alice", &err);
if (n < 0) { /* обробити err */ }
printf("%lld замін\n", (long long)n);
if (office_editable_save(ed, "out.docx", &err) != 0) { /* обробити err */ }
office_editable_free(ed);
Запис клітинок XLSX:
OfficeEditableHandle *wb = office_editable_open("budget.xlsx", &err);
office_editable_set_cell(wb, 0, "A1", OFFICE_CELL_STRING, "Total", 0.0, &err);
office_editable_set_cell(wb, 0, "B1", OFFICE_CELL_NUMBER, NULL, 42.5, &err);
office_editable_set_cell(wb, 0, "C1", OFFICE_CELL_BOOLEAN, NULL, 1.0, &err);
office_editable_set_cell(wb, 0, "D1", OFFICE_CELL_EMPTY, NULL, 0.0, &err);
office_editable_save(wb, "budget.xlsx", &err);
office_editable_free(wb);
Для булевих: value_num ≠ 0 означає true.
Серіалізація в heap-буфер:
size_t out_len = 0;
uint8_t *buf = office_editable_save_to_bytes(ed, &out_len, &err);
if (!buf) { /* обробити err */ }
/* завантажити або стрімити buf[0..out_len] */
office_oxide_free_bytes(buf, out_len);
Одноразові помічники
char *text = office_extract_text("file.docx", &err);
char *md = office_to_markdown("file.pptx", &err);
char *html = office_to_html("file.xlsx", &err);
/* кожен звільняти через office_oxide_free_string */
Правила роботи з пам’яттю
char*, що повертаютьoffice_document_*,office_editable_*та одноразові помічники, звільняйте черезoffice_oxide_free_string(ptr).uint8_t*(з out-параметромout_len) звільняйте черезoffice_oxide_free_bytes(ptr, len).lenмає збігатися зі значенням, яке API записав уout_len.- Непрозорі handles звільняйте парним
*_free(). const char*, що повертаютьoffice_oxide_version,office_oxide_detect_format,office_document_format— статичні. Не звільняти.
Помилки
Кожен виклик із можливою помилкою приймає int *error_code як out-параметр:
int err = 0;
OfficeDocumentHandle *doc = office_document_open("missing.docx", &err);
if (!doc) {
switch (err) {
case OFFICE_ERR_IO: fputs("io помилка\n", stderr); break;
case OFFICE_ERR_PARSE: fputs("помилка парсингу\n", stderr); break;
/* ... */
}
}
| Макрос | Значення | Сенс |
|---|---|---|
OFFICE_OK |
0 | успіх |
OFFICE_ERR_INVALID_ARG |
1 | nil-вказівник / невідомий рядок формату |
OFFICE_ERR_IO |
2 | помилка файлової системи |
OFFICE_ERR_PARSE |
3 | пошкоджений документ |
OFFICE_ERR_EXTRACTION |
4 | парсинг ОК, але рендер не вдався |
OFFICE_ERR_INTERNAL |
5 | баг — заведіть issue |
OFFICE_ERR_UNSUPPORTED |
6 | розширення/фіча не підтримується |
Константи значень клітинок
| Макрос | Значення |
|---|---|
OFFICE_CELL_EMPTY |
0 |
OFFICE_CELL_STRING |
1 |
OFFICE_CELL_NUMBER |
2 |
OFFICE_CELL_BOOLEAN |
3 |
Legacy-формати
Відкривайте через office_document_open — формат визначається за розширенням, верифікується magic-байтами. office_document_save_as прозоро конвертує legacy → OOXML:
OfficeDocumentHandle *doc = office_document_open("old.xls", &err);
office_document_save_as(doc, "modern.xlsx", &err);
office_document_free(doc);
Потокобезпека
Кожна handle належить викликаючому — не діліть одну handle між потоками. Різні handles можна використовувати паралельно; сама бібліотека реентерабельна.
C++
Заголовок обгорнуто в extern "C"-гарди, тож він заходить прямо в C+±юніт компіляції:
#include "office_oxide.h"
Поєднуйте з RAII-обгортками (std::unique_ptr<OfficeDocumentHandle, decltype(&office_document_free)>), щоб очищення було exception-safe.
Діагностика
| Симптом | Що робити |
|---|---|
Лінкер: undefined reference to office_document_open |
Додайте -loffice_oxide та відповідний -L; переконайтеся, що бібліотека зібрана --release --lib. |
Рантайм: error while loading shared libraries: liboffice_oxide.so |
Додайте каталог бібліотеки до LD_LIBRARY_PATH (Linux), DYLD_LIBRARY_PATH (macOS) або покладіть поряд із exe (Windows). |
OFFICE_ERR_INVALID_ARG для open_from_bytes |
format має бути точно `“docx” |
| Подвійне звільнення або пошкодження heap | Кожен char* звільняйте через office_oxide_free_string, кожен байтовий буфер через office_oxide_free_bytes(ptr, len) з оригінальним out_len. |
office_editable_replace_text повертає 0 на XLSX |
Очікувана поведінка — для редагування таблиць використовуйте office_editable_set_cell. |
Дивіться також
- Rust-крейт — базове ядро
- Go-прив’язка — використовує те саме C ABI через cgo
- C#-прив’язка — використовує те саме C ABI через P/Invoke