A cross-platform PDF processing library built in Rust with FFI bindings for mobile and desktop applications.
- PDF Information: Get page count, file size, and validation
- PDF Merging: Combine multiple PDF files using advanced lopdf techniques
- Cross-Platform: Works on macOS, iOS, Android, and Linux
- Mobile-Optimized: Pure Rust implementation for mobile platforms
- FFI Interface: C-compatible API for integration with mobile apps
- Command Line Tool: Standalone binary for desktop usage
| Platform | Status | Implementation |
|---|---|---|
| macOS | β | qpdf + lopdf |
| iOS | β | Pure lopdf |
| Android | β | Pure lopdf |
| Linux | β | qpdf + lopdf |
| Windows | π‘ | Not tested |
- Rust (latest stable)
- qpdf (for desktop platforms)
- Android NDK (for Android builds)
- Xcode (for iOS builds)
# Clone the repository
git clone <repository-url>
cd spdfcore
# Build the library
cargo build --release
# Build for specific platforms
make mac # macOS build
make android # Android build (all architectures)
make ios # iOS build# Get PDF information
./target/release/spdfcore info document.pdf
# Merge PDF files
./target/release/spdfcore merge file1.pdf file2.pdf file3.pdf output.pdf
# Split PDF at specific page
./target/release/spdfcore split document.pdf 5 output_prefix#include "spdfcore.h"
// Initialize the library
spdfcore_init();
// Get page count
int page_count;
PdfErrorCode error_code;
char* error_message;
bool success = pdf_get_page_count(
"document.pdf",
&page_count,
&error_code,
&error_message
);
if (success) {
printf("PDF has %d pages\n", page_count);
}
// Merge PDFs
const char* input_files[] = {"file1.pdf", "file2.pdf", NULL};
success = pdf_merge_files(
input_files,
"merged.pdf",
&error_code,
&error_message
);
// Cleanup
spdfcore_cleanup();use spdfcore::merge_real::merge_pdfs;
// Merge PDF files
let files = vec![
"file1.pdf".to_string(),
"file2.pdf".to_string(),
"file3.pdf".to_string(),
];
match merge_pdfs(&files, "output.pdf") {
Ok(()) => println!("β
Merge successful!"),
Err(e) => eprintln!("β Error: {}", e),
}src/core.rs- Essential PDF operations (page count, validation, file size)src/merge_real.rs- PDF merging implementation using lopdfsrc/ffi.rs- FFI interface for mobile/C integrationsrc/main.rs- Command line interfacesrc/error.rs- Error handling and typessrc/types.rs- Data structures and type definitions
On Android and iOS, spdfcore uses a pure Rust implementation with the lopdf library to ensure compatibility with mobile app sandboxes and App Store requirements.
On Desktop platforms, spdfcore can leverage external tools like qpdf for enhanced functionality while falling back to pure Rust when needed.
# Install Android targets
rustup target add aarch64-linux-android
rustup target add armv7-linux-androideabi
rustup target add i686-linux-android
rustup target add x86_64-linux-android
# Build for Android
make androidOutput: target/android/ with libraries for all architectures
# Install iOS targets
rustup target add aarch64-apple-ios
rustup target add x86_64-apple-ios
# Build for iOS
make iosmake mac| Function | Description |
|---|---|
spdfcore_init() |
Initialize the library |
spdfcore_cleanup() |
Clean up resources |
pdf_get_page_count() |
Get number of pages in PDF |
pdf_get_file_size() |
Get PDF file size in bytes |
pdf_validate() |
Validate PDF file |
pdf_merge_files() |
Merge multiple PDF files |
pdf_split_at_page() |
Split PDF at specific page |
| Code | Description |
|---|---|
Success |
Operation completed successfully |
FileNotFound |
PDF file not found |
InvalidPdf |
Invalid or corrupted PDF |
InvalidParameter |
Invalid function parameter |
IoError |
File I/O error |
UnsupportedFeature |
Feature not implemented |
# Run tests
cargo test
# Build and test Android
make android
# Test CLI
./target/release/spdfcore info test.pdf- Copy
target/android/folder to your Android project - Add to
build.gradle:android { sourceSets { main { jniLibs.srcDirs = ['src/main/jniLibs'] } } }
- Use
SpdfCore.javafor JNI interface
- Add the compiled library to your Xcode project
- Include
spdfcore.hheader - Call FFI functions from Objective-C/Swift
import 'dart:ffi';
import 'package:ffi/ffi.dart';
// Load the library
final DynamicLibrary spdfcore = DynamicLibrary.open('libspdfcore_ffi.so');
// Define function signatures
typedef GetPageCountC = Bool Function(Pointer<Utf8>, Pointer<Int32>, Pointer<Int32>, Pointer<Pointer<Utf8>>);
typedef GetPageCountDart = bool Function(Pointer<Utf8>, Pointer<Int32>, Pointer<Int32>, Pointer<Pointer<Utf8>>);
// Get function
final getPageCount = spdfcore.lookupFunction<GetPageCountC, GetPageCountDart>('pdf_get_page_count');
// Use the function
final path = 'document.pdf'.toNativeUtf8();
final pageCount = calloc<Int32>();
final errorCode = calloc<Int32>();
final errorMessage = calloc<Pointer<Utf8>>();
final success = getPageCount(path, pageCount, errorCode, errorMessage);spdfcore/
βββ src/
β βββ main.rs # CLI application
β βββ lib.rs # Library entry point
β βββ core.rs # Core PDF operations (25 lines)
β βββ merge_real.rs # PDF merging (120 lines)
β βββ ffi.rs # FFI interface
β βββ error.rs # Error handling
β βββ types.rs # Type definitions (47 lines)
βββ scripts/
β βββ build-android.sh # Android build script
β βββ build-ios.sh # iOS build script
β βββ build-mac.sh # macOS build script
β βββ README.md # Scripts documentation
βββ target/ # Build outputs (gitignored)
βββ Cargo.toml # Rust project configuration
βββ Makefile # Build system (20+ targets)
βββ cbindgen.toml # C header generation
βββ README.md # This file
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Android Build Fails:
- Ensure Android NDK is installed and
ANDROID_NDK_HOMEis set - Install required Rust targets:
rustup target add aarch64-linux-android
PDF Merge Fails:
- Verify input PDF files are valid and readable
- Check file permissions
- Ensure sufficient disk space for output
qpdf Not Found:
- Install qpdf:
brew install qpdf(macOS) orapt install qpdf(Linux) - spdfcore will fall back to pure Rust implementation
- lopdf - Pure Rust PDF library for mobile compatibility
- qpdf - External tool for advanced PDF operations (desktop only)
- cbindgen - C header generation
- Standard Rust libraries for cross-platform support
- Memory Efficient: Streaming PDF processing where possible
- Mobile Optimized: Minimal dependencies for mobile platforms
- Fast Merging: Advanced object ID mapping for efficient PDF combination
- Small Binary Size: Optimized for mobile deployment
Made with β€οΈ in Rust | Cross-platform PDF processing for everyone