返回资讯中心
外部精选
软件工程
#社区热议

Zebkit 将 Chromium 引擎打包成可链接库

来源标题:Zebkit – Chromium as an embeddable library

Zebkit 把 Chromium 引擎做成一个可直接链接进应用的库,包含 Blink、V8、PDFium、FFmpeg 等组件,但不含 Chrome 浏览器或 Electron 运行时。它提供 Linux、macOS、Windows 统一 API,支持 C、C++、Rust、Python 和 JavaScript 调用,应用可保留自己的窗口与工具包。

Hacker NewsRiiiiichard2026/11/9 · 今天30 分钟阅读

以下正文由 AI 翻译自 Hacker News(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。

Chromium 的引擎作为一个库——轻量、快速、随处可用、易于集成。在 Linux、macOS 和 Windows 上只有一套 API,几行代码即可接入。zebkit 把 Chromium 的引擎做成了一个你可以链接进自己应用的库:包含 Blink、带全部 JIT 层的 V8、PDFium、FFmpeg 以及 Chrome 的其余组成部分,但不含 Chrome 浏览器的任何部分,也不含 Electron 的运行时。你的应用始终是你的:可以用 C、C++、Rust、Python 或 JavaScript 编写,拥有自己的窗口和工具包。需要网页时,加一个 zebkit 视图;需要 PDF、媒体、压缩或加密时,调用 zebkit 的 API:可用 C,也可通过 Rust、Python 和 JavaScript 绑定(zebkit-js,以及应用自身页面中的 zebkit.*)。

获取引擎

一个包就是一个目录,内含库、辅助程序、引擎数据和 include/。你可以解压某个 release 的归档(GitHub releases 中的 zebkit-<version>-<target>.tar.xz),也可以自行构建:

mise run r # dist/release(Linux)、dist/release-macos(macOS)、dist/release-windows;首次构建需要数小时

每个归档还包含为对应系统构建的工具,与库放在一起,解压后即可直接运行:zebkit-run、zebkit-js 和 zebkit-mcp(Windows 上为 .exe,同样在沙箱中运行)。在安装了完整 Xcode 的 Apple silicon Mac 上,scripts/dist.sh release 会在本地把引擎构建到 dist/release。然后运行 scripts/example.sh macos-basic,即可构建并启动 C 嵌入示例,位于 dist/example/Zebkit Embedded Browser.app。构建 Chromium 源码树约需 30 GB 空间(见 docs/BUILD.md)。下文中 $PKG 指包目录。

zebkit 是一个库:你的程序保留自己的 main() 并调用它。下面这个程序把 PDF 的第一页渲染为 PNG 并读取其文本,用的是 zebkit 内置的 PDFium 和图像编码器,无需安装其他东西:

#include <stdio.h>
#include <zebkit/pdf.h>
#include <zebkit/services.h>

/* Your program, your main(): zebkit is just a library it calls. */
int main(int argc, char **argv) {
    char *error = NULL;
    zebkit_pdf *pdf = zebkit_pdf_open_file(argv[1], NULL, &error);
    if (!pdf) {
        fprintf(stderr, "%s\n", error);
        return 1;
    }

    /* The first page as a PNG, at twice its size. */
    zebkit_pdf_render_options options = {.scale = 2, .background = 0xffffffff};
    int width, height;
    uint8_t *rgba = zebkit_pdf_render(pdf, 0, &options, &width, &height, &error);
    size_t size;
    uint8_t *png = zebkit_image_encode(ZEBKIT_IMAGE_PNG, rgba, width, height, 0, &size, &error);
    fwrite(png, 1, size, fopen("page1.png", "wb"));

    /* And its text. */
    char *text = zebkit_pdf_text(pdf, 0, &error);
    printf("%d pages; page 1 says: %.80s\n", zebkit_pdf_page_count(pdf), text);

    zebkit_free(text), zebkit_free(png), zebkit_free(rgba);
    zebkit_pdf_close(pdf);
    return 0;
}
cc thumb.c -I$PKG/include -L$PKG -l:libzebkit.so.1 -Wl,-rpath,$PKG -o thumb # Linux
cc thumb.c -I$PKG/include -F$PKG -framework Zebkit -Wl,-rpath,$PKG -o thumb # macOS
./thumb report.pdf # 2 pages; page 1 says: Quarterly report ...

PDF API、压缩、加密、URL、图像编解码器、ICU 以及引擎内部的其他库(zebkit_vendor_*,包括 FFmpeg 的库)都不需要引擎循环(见 docs/API.md);只有通过引擎网络栈发起的 HTTP 请求和网页需要。

网页需要引擎运行。这时由引擎来跑循环:程序用 zebkit_main() 启动它,并在其回调中工作。自带循环的程序(GTK、Qt、AppKit、winit)用 zebkit_init() 启动,并调用 zebkit_pump()(见 examples/native-host)。

#include <stdio.h>
#include <zebkit/zebkit.h>

static void printed(zebkit_view *view, const char *json, const char *error, void *data) {
    printf("%s\n", json ? json : error);
    zebkit_quit();
}

static void loaded(zebkit_view *view, zebkit_load_event event, const char *url, void *data) {
    if (event == ZEBKIT_LOAD_FINISHED)
        zebkit_view_evaluate(view, "document.title", printed, NULL);
}

static void ready(void *data) {
    zebkit_view *view = zebkit_view_new("https://example.com/", 1024, 768);
    zebkit_view_on_load(view, loaded, NULL);
}

int main(int argc, char **argv) {
    return zebkit_main(argc, argv, ready, NULL);
}
cc app.c -I$PKG/include -L$PKG -l:libzebkit.so.1 -Wl,-rpath,$PKG -o app # Linux
cc app.c -I$PKG/include -F$PKG -framework Zebkit -Wl,-rpath,$PKG -o app # macOS
clang-cl /MT app.c /I%PKG%\include %PKG%\zebkit.dll.lib %PKG%\zebkit_sandbox.lib # Windows
./app --remote-debugging-port=9222 # with CDP for Puppeteer and Playwright

在 Windows 上,可执行文件参与 Chromium 的沙箱:它链接 zebkit_sandbox.lib,并在 main() 中首先调用 zebkit_win_startup()(见 docs/WINDOWS.md)。如果没有非特权用户命名空间,引擎会拒绝启动并说明原因:安装其辅助程序,或在自有的容器中添加 --no-sandbox(见 docs/SANDBOX.md)。

应用通过自定义 scheme 提供自己的页面,并赋予页面可调用的函数;除非被授予,页面与 zebkit 毫无关联。

/* The page calls zebkit.app.greet("Ada"). */
static void greet(zebkit_view *view, const char *origin, const char *args_json,
                  zebkit_call *call, void *data) {
    char answer[256];
    snprintf(answer, sizeof answer, "{\"hello\": %s}", args_json);
    zebkit_call_resolve(call, answer);
}

/* app://main/... from ./ui, in ranges for media. A real handler refuses "..". */
static void serve(zebkit_request *request, void *data) {
    char path[1024];
    snprintf(path, sizeof path, "ui%s", zebkit_request_url(request) + sizeof "app://main" - 1);
    zebkit_request_respond_file(request, path, NULL);
}

static void closed(zebkit_view *view, void *data) { zebkit_quit(); }

static void ready(void *data) {
    zebkit_view *view = zebkit_view_new("app://main/index.html", 1024, 768);
    zebkit_view_grant(view, "app://main", ZEBKIT_ALLOW_APP | ZEBKIT_ALLOW_PDF, NULL);
    zebkit_view_bind(view, "greet", greet, NULL);
    zebkit_view_on_close(view, closed, NULL);
}

int main(int argc, char **argv) {
    zebkit_scheme_register("app", ZEBKIT_SCHEME_STANDARD | ZEBKIT_SCHEME_SECURE | ZEBKIT_SCHEME_FETCH);
    zebkit_scheme_handle("app", serve, NULL);
    return zebkit_main(argc, argv, ready, NULL);
}

(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →