Primeros pasos con PDF Oxide (Objective-C)
PDF Oxide incluye bindings idiomáticos de Objective-C sobre su núcleo en Rust: 0,8 ms de media en la extracción de texto y un 100 % de aciertos sobre 3830 PDF. Los envoltorios NSObject (POXDocument, POXPdf) son dueños de los handles nativos y los liberan bajo ARC, las cadenas devueltas llegan como NSString y cualquier código de error del C-ABI se expone como un NSError en el POXErrorDomain. Novedad en la v0.3.69.
Instalación
El binding de Objective-C enlaza el cdylib con las features por defecto y se compila con clang bajo ARC. Compila la biblioteca nativa y, a continuación, ejecuta make build contra ella:
# 1. compila la biblioteca nativa (conjunto de features del binding)
cargo build --release --lib --features ocr,rendering,signatures,barcodes,tsa-client,system-fonts
# 2. compila el binding de Objective-C (clang, ARC)
cd objc
make build PDF_OXIDE_LIB_DIR="$PWD/../target/release"
DYLD_LIBRARY_PATH="$PWD/../target/release" ./basic_extraction
Importa la única cabecera pública en tus fuentes:
#import "POXPdfOxide.h"
Inicio rápido
Abre un PDF, inspecciona sus metadatos y extrae el texto de la primera página. Toda llamada que pueda fallar recibe un NSError** como último parámetro.
#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);
También puedes abrir desde bytes en memoria —útil cuando el PDF llega por la red o desde una base de datos— y abrir archivos protegidos con contraseña:
POXDocument *doc = [POXDocument openFromBytes:pdfData error:&err];
// Documento cifrado, con la contraseña indicada de antemano:
POXDocument *enc = [POXDocument openWithPassword:@"confidential.pdf"
password:@"secret"
error:&err];
// O autentícate después de abrirlo:
BOOL ok = [doc authenticate:@"secret" error:&err];
Extracción de texto
El texto plano es la vía rápida. Extrae una única página por su índice de base cero, o recupera el documento entero de una sola vez.
// Una página
NSString *text = [doc extractText:0 error:&err];
// Documento completo, unido
NSString *all = [doc toPlainTextAllWithError:&err];
// Página a página
NSInteger count = [doc pageCountError:&err];
for (NSInteger i = 0; i < count; i++) {
NSLog(@"--- page %ld ---\n%@", (long)i, [doc extractText:i error:&err]);
}
Palabras y líneas
extractWords: y extractTextLines: devuelven arrays de objetos de elemento con sus bounding boxes y metadatos de fuente, todo en puntos del espacio de usuario del 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 (procedente de extractChars:) expone la misma estructura con granularidad de carácter: character, bbox, fontName y fontSize.
Markdown y HTML
Convierte una página —o el documento entero— a Markdown o HTML.
// Una sola página
NSString *md = [doc toMarkdown:0 error:&err];
NSString *html = [doc toHtml:0 error:&err];
// Documento completo
NSString *mdAll = [doc toMarkdownAllWithError:&err];
NSString *htmlAll = [doc toHtmlAllWithError:&err];
Búsqueda
Busca en una sola página con search:term:caseSensitive:error:, o en todo el documento con searchAll:caseSensitive:error:. Ambos devuelven arrays de POXSearchResult que llevan el texto coincidente, el índice de página y el bounding box.
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);
}
// Variante de una sola página:
NSArray<POXSearchResult *> *pageHits =
[doc search:0 term:@"configuration" caseSensitive:NO error:&err];
Creación de PDF
El constructor POXPdf genera PDF a partir de Markdown, HTML o texto plano. Guárdalos en una ruta o recupera los bytes como NSData.
POXPdf *pdf = [POXPdf fromMarkdown:@"# Hello World\n\nThis is a PDF.\n"
error:&err];
[pdf saveToPath:@"output.pdf" error:&err];
// O conserva los bytes en memoria
NSData *bytes = [pdf toBytesWithError:&err];
// También existen constructores para HTML y texto plano
POXPdf *invoice = [POXPdf fromHtml:@"<h1>Invoice</h1><p>Amount: $42</p>"
error:&err];
POXPdf *notes = [POXPdf fromText:@"Plain text content." error:&err];
Ve de ida y vuelta desde un constructor directamente a un documento para extraer:
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]);
Manejo de errores
Cada método que puede fallar escribe en el NSError** final y devuelve nil / un valor centinela en caso de fallo. Los errores aterrizan en el 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);
}
Los handles se liberan solos bajo ARC, pero puedes liberar el handle nativo de inmediato con -close (idempotente):
[doc close];
Próximos pasos
- Primeros pasos con Rust — uso de PDF Oxide desde Rust
- Primeros pasos con Python — uso de PDF Oxide desde Python
- Extracción de texto — opciones y recetas de extracción en detalle
- Creación de PDF — creación avanzada con la API del constructor
- Edición — modificación de PDF existentes, anotaciones y campos de formulario