I want to make a project where I am using GitHub - tesseract-ocr/tesseract: Tesseract Open Source OCR Engine (main repository). The problem is, that the project is written in cpp. My question: How can I include this in my project?
First you need to build the library and find a simple working C example.
In your build.zig
file add exe.linkSystemLibrary("tesseract");
You might also need to add where are the libraries and include files:
exe.addIncludePath(.{.cwd_relative = "/path/to/tesseract/include"});
exe.addLibraryPath(.{.cwd_relative = "/path/to/lib"});
In your zig source file add:
const tesseract = @cImport({
// add all the include files required for the C API
@cInclude("capi.h");
});
pub fn main() void {
const handle = tesseract.TessBaseAPICreate();
defer tesseract.TessBaseAPIDelete(handle);
}
Translate the C API example to zig calls like the calls to TessBaseAPICreate
.
Wait so ideally I need to find an example of someone who managed to do this in c and then just replicate it, so first statically compile the library and then include and statically link it?
There are examples in the User Guide.
Search for “Example using the C-API in a C program”.
I just found em too, I’ll give them a try probably tomorrow
I have tried this, but baseapi.h is a hpp in disguise
Zig cannot call/include C++ code but you can use the C API since the library have both a C and C++ API.
Im a bit lost here, I dont know what I’m doing wrong.
My build file:
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "document-sorter",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
exe.linkLibC();
exe.linkSystemLibrary("tesseract");
// exe.addIncludePath(b.path("include/tesseract/include/tesseract/"));
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args|
run_cmd.addArgs(args);
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
const exe_unit_tests = b.addTest(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&run_exe_unit_tests.step);
}
My main file:
const std = @import("std");
const c = @cImport({
@cInclude("tesseract/baseapi.h");
// @cInclude("baseapi.h");
});
pub fn main() !void {
_ = c;
unreachable;
}
The commented out lines are there because I also have the repo cloned and tried to include it that way. In both cases I got the exact same error:
install
└─ install document-sorter
└─ zig build-exe document-sorter Debug native 6 errors
src/main.zig:2:11: error: C import failed
const c = @cImport({
^~~~~~~~
referenced by:
main: src/main.zig:8:9
callMain: /home/segfault-enjoyer/.bin/lib/std/start.zig:524:32
remaining reference traces hidden; use '-freference-trace' to see all reference traces
/usr/include/tesseract/publictypes.h:20:1: error: unknown type name 'namespace'
namespace tesseract {
^
/usr/include/tesseract/publictypes.h:20:20: error: expected ';' after top level declarator
namespace tesseract {
^
/usr/include/tesseract/pageiterator.h:27:1: error: unknown type name 'namespace'
namespace tesseract {
^
/usr/include/tesseract/pageiterator.h:27:20: error: expected ';' after top level declarator
namespace tesseract {
^
/usr/include/tesseract/unichar.h:23:10: error: 'cstring' file not found
#include <cstring>
^
which is clearly just the zig compiler having a stroke upon seeing cpp (very understandable ngl)
Zig cannot parse baseapi.h
because it is C++.
include the capi.h
file.
const std = @import("std");
const c = @cImport({
@cInclude("tesseract/capi.h");
});
pub fn main() !void {
_ = c;
unreachable;
}
Oh lol you’re right. I though that capi.h
was just something left from a copy paste of sorts and didn’t know it actually existed. I appreciate your help and persistence despite my misunderstandings!
Hehe one more question: How could I link this statically?
linkSystemLibrary2 have LinkSystemLibraryOptions
exe.linkSystemLibrary2("tesseract", .{ .preferred_link_mode = .static });
Is it possible to do this via the cloned project too? I would find it very nice if I can just copy this to any of my machines and instantly compile it without having to rely on the repos having tesseract.
Also, does preferred_link_mode enforce static linking here or “politely ask”?