A C library for reading and writing EPUB.
Debian / Ubuntu
apt install libxml2-dev zlib1g-dev libminizip-dev
macOS (Homebrew)
brew install libxml2 zlib minizip
Arch Linux
pacman -S libxml2 zlib minizip
cmake -B build -DWITH_TESTS=ON -DWITH_EXAMPLES=ON
cmake --build build
ctest --test-dir build
cmake --install build --prefix /usr/localmeson setup build -Dtests=true -Dexamples=true
ninja -C build
meson test -C build
ninja -C build installThe library has three abstraction levels:
Level 1 — ZIP layer epub_zip.c
Raw archive entry listing and read/write via minizip.
epub_list_entries(), epub_read_entry()
Level 2 — Document layer epub.c epub_util.c
XML parsing (libxml2), OPF/NCX/container.xml.
Escape-hatch xmlDoc* access via epub_xml.h.
Level 3 — Public API epub_metadata epub_spine epub_nav epub_writer
Stable C interface; all structs are opaque.
Module map:
| File | Responsibility |
|---|---|
epub.h |
epub_open, epub_open_memory, epub_close, epub_save, Level 1 API |
epub_types.h |
Error codes, enums, forward declarations |
epub_xml.h |
Escape-hatch xmlDoc* access (requires libxml2 headers) |
epub_metadata.h |
Metadata getters/setters incl. multiple authors, description, rights, subjects |
epub_spine.h |
Spine traversal, item content read, overlay access |
epub_nav.h |
Navigation/TOC traversal and building |
epub_writer.h |
Build and save new EPUB files, save_memory |
epub_internal.h |
Private struct definitions (not installed) |
epub_zip.c |
minizip wrapper |
epub_overlay.c |
Media Overlay (SMIL) stub |
epub_util.c |
String helpers, XML helpers, media type parsing |
epub_open/epub_open_memoryreturn a heap-allocated handle — caller must callepub_close.epub_writer_newreturns a heap-allocated handle — caller must callepub_writer_free.- All
const char *returned by getters are owned by the handle — do not free. epub_spine_item_readandepub_read_entryreturn caller-owned buffers — caller mustfree().epub_writer_save_memoryreturns a caller-owned buffer — caller mustfree().epub_list_entriesreturns a caller-owned array of caller-owned strings — free each string, then the array.
epub_t *epub_open(const char *path, epub_err_t *err);
epub_t *epub_open_memory(const uint8_t *data, size_t len, epub_err_t *err);
void epub_close(epub_t *epub);
epub_err_t epub_save(epub_t *epub, const char *path);
const char *epub_err_str(epub_err_t err);
epub_err_t epub_last_error(void);epub_err_t epub_list_entries(const epub_t *epub, char ***out_names, size_t *out_count);
uint8_t *epub_read_entry(const epub_t *epub, const char *entry_path,
size_t *out_size); /* caller frees */const char *epub_metadata_title(const epub_t *epub);
const char *epub_metadata_author(const epub_t *epub); /* first author */
size_t epub_metadata_author_count(const epub_t *epub);
const char *epub_metadata_author_at(const epub_t *epub, size_t index);
const char *epub_metadata_publisher(const epub_t *epub);
const char *epub_metadata_language(const epub_t *epub);
const char *epub_metadata_identifier(const epub_t *epub);
const char *epub_metadata_date(const epub_t *epub);
const char *epub_metadata_description(const epub_t *epub);
const char *epub_metadata_rights(const epub_t *epub);
size_t epub_metadata_subject_count(const epub_t *epub);
const char *epub_metadata_subject_at(const epub_t *epub, size_t index);
epub_version_t epub_metadata_version(const epub_t *epub);
epub_err_t epub_metadata_set_title(epub_t *epub, const char *title);
epub_err_t epub_metadata_set_author(epub_t *epub, const char *author); /* replaces all */
epub_err_t epub_metadata_add_author(epub_t *epub, const char *author);
epub_err_t epub_metadata_set_language(epub_t *epub, const char *language);
epub_err_t epub_metadata_set_identifier(epub_t *epub, const char *identifier);
epub_err_t epub_metadata_set_description(epub_t *epub, const char *description);
epub_err_t epub_metadata_set_rights(epub_t *epub, const char *rights);
epub_err_t epub_metadata_add_subject(epub_t *epub, const char *subject);const epub_spine_t *epub_spine_get(const epub_t *epub);
size_t epub_spine_count(const epub_spine_t *spine);
const epub_spine_item_t *epub_spine_item_at(const epub_spine_t *spine, size_t index);
const char *epub_spine_item_idref(const epub_spine_item_t *item);
const char *epub_spine_item_href(const epub_spine_item_t *item);
epub_media_type_t epub_spine_item_media_type(const epub_spine_item_t *item);
const char *epub_spine_item_media_type_str(const epub_spine_item_t *item);
int epub_spine_item_is_linear(const epub_spine_item_t *item);
char *epub_spine_item_read(const epub_t *epub,
const epub_spine_item_t *item,
size_t *out_size); /* caller frees */
const epub_overlay_t *epub_spine_item_get_overlay(const epub_spine_item_t *item);const epub_nav_t *epub_nav_get(const epub_t *epub);
size_t epub_nav_count(const epub_nav_t *nav);
const epub_nav_point_t *epub_nav_point_at(const epub_nav_t *nav, size_t index);
const char *epub_nav_point_label(const epub_nav_point_t *point);
const char *epub_nav_point_href(const epub_nav_point_t *point);
size_t epub_nav_point_child_count(const epub_nav_point_t *point);
const epub_nav_point_t *epub_nav_point_child_at(const epub_nav_point_t *point,
size_t index);
epub_nav_point_t *epub_nav_add_point(epub_nav_t *nav, const char *label,
const char *href, epub_nav_point_t *parent,
epub_err_t *err);epub_writer_t *epub_writer_new(epub_version_t version); /* caller frees */
void epub_writer_free(epub_writer_t *writer);
epub_err_t epub_writer_set_title(epub_writer_t *writer, const char *title);
epub_err_t epub_writer_set_author(epub_writer_t *writer, const char *author);
epub_err_t epub_writer_add_author(epub_writer_t *writer, const char *author);
epub_err_t epub_writer_set_language(epub_writer_t *writer, const char *language);
epub_err_t epub_writer_set_identifier(epub_writer_t *writer, const char *identifier);
epub_err_t epub_writer_add_chapter(epub_writer_t *writer, const char *id,
const char *filename, const char *content,
size_t size);
epub_err_t epub_writer_add_resource(epub_writer_t *writer, const char *id,
const char *filename, const char *media_type,
const unsigned char *data, size_t size);
epub_nav_t *epub_writer_get_nav(epub_writer_t *writer);
epub_err_t epub_writer_save(epub_writer_t *writer, const char *path);
epub_err_t epub_writer_save_memory(epub_writer_t *writer, uint8_t **out_data,
size_t *out_len); /* caller frees *out_data */#include <epub/epub_xml.h>
xmlDoc *epub_spine_item_get_xmldoc(const epub_t *epub, const epub_spine_item_t *item);