Начало работы с PDF Oxide (Objective-C)
PDF Oxide поставляется с идиоматичными привязками для Objective-C поверх ядра на Rust — в среднем 0.8 мс на извлечение текста, 100% успешных проверок на 3830 PDF. Обёртки NSObject (POXDocument, POXPdf) владеют нативными дескрипторами и освобождают их под ARC, возвращаемые строки приходят как NSString, а любой код ошибки C-ABI всплывает как NSError в домене POXErrorDomain. Новое в v0.3.69.
Установка
Привязка для Objective-C линкуется с cdylib (набор возможностей по умолчанию) и собирается через clang под ARC. Соберите нативную библиотеку, затем выполните make build против неё:
# 1. собираем нативную библиотеку (поставляемый набор возможностей привязки)
cargo build --release --lib --features ocr,rendering,signatures,barcodes,tsa-client,system-fonts
# 2. собираем привязку для Objective-C (clang, ARC)
cd objc
make build PDF_OXIDE_LIB_DIR="$PWD/../target/release"
DYLD_LIBRARY_PATH="$PWD/../target/release" ./basic_extraction
Подключите единственный публичный заголовок в своих исходниках:
#import "POXPdfOxide.h"
Быстрый старт
Откройте PDF, изучите его метаданные и извлеките текст с первой страницы. Каждый вызов, который может завершиться ошибкой, принимает завершающий аргумент NSError**.
#import "POXPdfOxide.h"
NSError *err = nil;
POXDocument *doc = [POXDocument openPath:@"research-paper.pdf" error:&err];
if (!doc) {
NSLog(@"open failed: %@", err.localizedDescription);
return;
}
NSInteger pages = [doc pageCountError:&err];
POXVersion ver = [doc version];
NSLog(@"pages: %ld version: %d.%d", (long)pages, ver.major, ver.minor);
NSString *text = [doc extractText:0 error:&err];
NSLog(@"%@", text);
Можно также открыть документ из байтов в памяти — это удобно, когда PDF приходит по сети или из базы данных, — и открывать файлы, защищённые паролем:
POXDocument *doc = [POXDocument openFromBytes:pdfData error:&err];
// Зашифрованный документ, пароль передан сразу:
POXDocument *enc = [POXDocument openWithPassword:@"confidential.pdf"
password:@"secret"
error:&err];
// Или аутентификация уже после открытия:
BOOL ok = [doc authenticate:@"secret" error:&err];
Извлечение текста
Простой текст — самый быстрый путь. Извлеките одну страницу по её индексу (отсчёт с нуля) или весь документ сразу.
// Одна страница
NSString *text = [doc extractText:0 error:&err];
// Весь документ, объединённый
NSString *all = [doc toPlainTextAllWithError:&err];
// Постранично
NSInteger count = [doc pageCountError:&err];
for (NSInteger i = 0; i < count; i++) {
NSLog(@"--- page %ld ---\n%@", (long)i, [doc extractText:i error:&err]);
}
Слова и строки
extractWords: и extractTextLines: возвращают массивы объектов-элементов с ограничивающими прямоугольниками и метаданными шрифта — всё в точках пользовательского пространства PDF.
NSArray<POXWord *> *words = [doc extractWords:0 error:&err];
for (POXWord *w in words) {
POXBbox box = w.bbox;
NSLog(@"'%@' at (%.1f, %.1f) %.1fx%.1f font=%@ size=%.1f bold=%d",
w.text, box.x, box.y, box.width, box.height,
w.fontName, w.fontSize, w.bold);
}
NSArray<POXTextLine *> *lines = [doc extractTextLines:0 error:&err];
for (POXTextLine *line in lines) {
NSLog(@"%@ (%ld words)", line.text, (long)line.wordCount);
}
POXChar (из extractChars:) предоставляет ту же структуру на уровне отдельных символов — character, bbox, fontName и fontSize.
Markdown и HTML
Преобразуйте страницу — или весь документ — в Markdown или HTML.
// Одна страница
NSString *md = [doc toMarkdown:0 error:&err];
NSString *html = [doc toHtml:0 error:&err];
// Весь документ
NSString *mdAll = [doc toMarkdownAllWithError:&err];
NSString *htmlAll = [doc toHtmlAllWithError:&err];
Поиск
Ищите по одной странице с помощью search:term:caseSensitive:error: или по всему документу с помощью searchAll:caseSensitive:error:. Оба метода возвращают массивы POXSearchResult, несущие найденный текст, индекс страницы и ограничивающий прямоугольник.
NSArray<POXSearchResult *> *hits =
[doc searchAll:@"configuration" caseSensitive:NO error:&err];
for (POXSearchResult *r in hits) {
POXBbox b = r.bbox;
NSLog(@"page %ld: '%@' at (%.0f, %.0f)", (long)r.page, r.text, b.x, b.y);
}
// Вариант для одной страницы:
NSArray<POXSearchResult *> *pageHits =
[doc search:0 term:@"configuration" caseSensitive:NO error:&err];
Создание PDF
Построитель POXPdf создаёт PDF из Markdown, HTML или простого текста. Сохраните результат в файл или получите байты обратно как NSData.
POXPdf *pdf = [POXPdf fromMarkdown:@"# Hello World\n\nThis is a PDF.\n"
error:&err];
[pdf saveToPath:@"output.pdf" error:&err];
// Или оставьте байты в памяти
NSData *bytes = [pdf toBytesWithError:&err];
// Также есть конструкторы для HTML и простого текста
POXPdf *invoice = [POXPdf fromHtml:@"<h1>Invoice</h1><p>Amount: $42</p>"
error:&err];
POXPdf *notes = [POXPdf fromText:@"Plain text content." error:&err];
Сразу пропустите результат построителя в документ для извлечения:
POXPdf *pdf = [POXPdf fromMarkdown:@"# Report\n\nBody text.\n" error:&err];
POXDocument *doc = [POXDocument openFromBytes:[pdf toBytesWithError:&err]
error:&err];
NSLog(@"%@", [doc extractText:0 error:&err]);
Обработка ошибок
Каждый метод, способный завершиться ошибкой, пишет в завершающий аргумент NSError** и возвращает nil / специальное значение-маркер при сбое. Ошибки попадают в домен POXErrorDomain.
NSError *err = nil;
POXDocument *doc = [POXDocument openPath:@"document.pdf" error:&err];
if (!doc) {
if ([err.domain isEqualToString:POXErrorDomain]) {
NSLog(@"PDF error: %@", err.localizedDescription);
}
return;
}
NSString *text = [doc extractText:0 error:&err];
if (!text) {
NSLog(@"extract failed: %@", err.localizedDescription);
}
Дескрипторы освобождаются сами под ARC, но вы можете заранее освободить нативный дескриптор с помощью -close (идемпотентно):
[doc close];
Дальнейшие шаги
- Начало работы с Rust — использование PDF Oxide из Rust
- Начало работы с Python — использование PDF Oxide из Python
- Извлечение текста — подробные параметры и рецепты извлечения
- Создание PDF — продвинутое создание с помощью API построителя
- Редактирование — изменение существующих PDF, аннотаций и полей форм