zig-cinterop
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseZig C Interop
Zig与C互操作
Purpose
用途
Guide agents through Zig's C interoperability: / for calling C, for header inspection, and for ABI-compatible types, exporting Zig for C consumption, and for mixed C/Zig builds.
@cImport@cIncludetranslate-cextern structpacked structzig cc指导开发者掌握Zig与C的互操作:使用/调用C代码,使用检查头文件,使用和定义兼容ABI的类型,将Zig代码导出供C调用,以及使用构建C/Zig混合项目。
@cImport@cIncludetranslate-cextern structpacked structzig ccTriggers
触发场景
- "How do I call a C function from Zig?"
- "How do I use @cImport and @cInclude?"
- "How do I export Zig functions to be called from C?"
- "How do I define a struct that matches a C struct?"
- "What does translate-c do?"
- "How do I build a mixed C and Zig project?"
- "如何从Zig调用C函数?"
- "如何使用@cImport和@cInclude?"
- "如何将Zig函数导出供C调用?"
- "如何定义与C结构体匹配的结构体?"
- "translate-c的作用是什么?"
- "如何构建C与Zig的混合项目?"
Workflow
操作流程
1. Calling C from Zig with @cImport
1. 使用@cImport从Zig调用C代码
zig
const c = @cImport({
@cInclude("stdio.h");
@cInclude("string.h");
@cInclude("mylib.h");
@cDefine("MY_FEATURE", "1"); // Equivalent to -DMY_FEATURE=1
@cUndef("SOME_MACRO");
});
pub fn main() void {
_ = c.printf("Hello from C: %d\n", @as(c_int, 42));
var buf: [256]u8 = undefined;
_ = c.snprintf(&buf, buf.len, "formatted: %d", @as(c_int, 100));
}In :
build.zigzig
exe.linkLibC(); // Required when using C functions
exe.addIncludePath(b.path("include/"));zig
const c = @cImport({
@cInclude("stdio.h");
@cInclude("string.h");
@cInclude("mylib.h");
@cDefine("MY_FEATURE", "1"); // 等效于-DMY_FEATURE=1
@cUndef("SOME_MACRO");
});
pub fn main() void {
_ = c.printf("Hello from C: %d\n", @as(c_int, 42));
var buf: [256]u8 = undefined;
_ = c.snprintf(&buf, buf.len, "formatted: %d", @as(c_int, 100));
}在中:
build.zigzig
exe.linkLibC(); // 使用C函数时必须添加
exe.addIncludePath(b.path("include/"));2. translate-c — inspect C header translation
2. translate-c — 检查C头文件翻译结果
translate-cbash
undefinedtranslate-cbash
undefinedTranslate a header file
翻译头文件
zig translate-c /usr/include/stdio.h > stdio.zig
zig translate-c /usr/include/stdio.h > stdio.zig
Translate with defines/includes
带宏定义和包含路径的翻译
zig translate-c -I include/ -DFEATURE=1 mylib.h > mylib.zig
zig translate-c -I include/ -DFEATURE=1 mylib.h > mylib.zig
Translate and inspect specific types
翻译并查看特定类型
zig translate-c mylib.h | grep -A5 "struct MyStruct"
This is Zig's equivalent of `bindgen` — you use it to understand what Zig generates, then use `@cImport` directly in code.zig translate-c mylib.h | grep -A5 "struct MyStruct"
这相当于Zig版本的`bindgen` — 你可以用它查看Zig生成的代码,然后在代码中直接使用`@cImport`。3. C type mapping
3. C类型映射
| C type | Zig type |
|---|---|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
zig
// Passing strings to C
const str = "hello";
_ = c.puts(str); // Zig string literals are [*:0]const u8
// Dynamic strings — need null terminator
var buf: [64:0]u8 = undefined;
const len = std.fmt.bufPrint(buf[0..63], "hello {d}", .{42}) catch unreachable;
buf[len] = 0;
_ = c.puts(&buf);| C类型 | Zig类型 |
|---|---|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
zig
// 向C传递字符串
const str = "hello";
_ = c.puts(str); // Zig字符串字面量默认是[*:0]const u8类型
// 动态字符串 — 需要添加空终止符
var buf: [64:0]u8 = undefined;
const len = std.fmt.bufPrint(buf[0..63], "hello {d}", .{42}) catch unreachable;
buf[len] = 0;
_ = c.puts(&buf);4. extern struct — ABI-compatible structs
4. extern struct — 兼容ABI的结构体
Use to match a C struct's memory layout exactly:
extern structzig
// Matches: struct Point { int x; int y; };
const Point = extern struct {
x: c_int,
y: c_int,
};
// Matches: struct Header { uint32_t magic; uint16_t version; uint16_t flags; };
const Header = extern struct {
magic: u32,
version: u16,
flags: u16,
};
// Use with C API
var p = Point{ .x = 10, .y = 20 };
_ = c.draw_point(&p);使用可以完全匹配C结构体的内存布局:
extern structzig
// 匹配C结构体:struct Point { int x; int y; };
const Point = extern struct {
x: c_int,
y: c_int,
};
// 匹配C结构体:struct Header { uint32_t magic; uint16_t version; uint16_t flags; };
const Header = extern struct {
magic: u32,
version: u16,
flags: u16,
};
// 与C API配合使用
var p = Point{ .x = 10, .y = 20 };
_ = c.draw_point(&p);5. packed struct — bit-level layout
5. packed struct — 位级布局
zig
// Matches C bitfield: struct { uint8_t flags : 4; uint8_t type : 4; };
const Flags = packed struct(u8) {
mode: u4,
kind: u4,
};
// Packed struct for wire protocols
const IpHeader = packed struct(u32) {
ihl: u4,
version: u4,
tos: u8,
total_length: u16,
};
var h: IpHeader = @bitCast(@as(u32, raw_bytes));zig
// 匹配C位域:struct { uint8_t flags : 4; uint8_t type : 4; };
const Flags = packed struct(u8) {
mode: u4,
kind: u4,
};
// 用于网络协议的packed结构体
const IpHeader = packed struct(u32) {
ihl: u4,
version: u4,
tos: u8,
total_length: u16,
};
var h: IpHeader = @bitCast(@as(u32, raw_bytes));6. Exporting Zig to C
6. 将Zig代码导出给C调用
zig
// Export a function callable from C
export fn zig_add(a: c_int, b: c_int) c_int {
return a + b;
}
// Export with specific calling convention
pub fn my_func(x: u32) callconv(.C) u32 {
return x * 2;
}
// Export a struct (use extern struct for C layout)
export const VERSION: c_int = 42;Generate a C header (manual or with tools):
c
/* mylib.h */
#ifndef MYLIB_H
#define MYLIB_H
#include <stdint.h>
int zig_add(int a, int b);
uint32_t my_func(uint32_t x);
extern int VERSION;
#endifzig
// 导出可被C调用的函数
export fn zig_add(a: c_int, b: c_int) c_int {
return a + b;
}
// 使用特定调用约定导出
pub fn my_func(x: u32) callconv(.C) u32 {
return x * 2;
}
// 导出结构体(使用extern struct保证C布局)
export const VERSION: c_int = 42;生成C头文件(手动或通过工具):
c
/* mylib.h */
#ifndef MYLIB_H
#define MYLIB_H
#include <stdint.h>
int zig_add(int a, int b);
uint32_t my_func(uint32_t x);
extern int VERSION;
#endif7. Calling Zig from C in build.zig
7. 在build.zig中配置从C调用Zig
zig
// Build Zig as a C-compatible static library
const lib = b.addStaticLibrary(.{
.name = "myzig",
.root_source_file = b.path("src/lib.zig"),
.target = target,
.optimize = optimize,
});
// The C code that uses the Zig library
const c_exe = b.addExecutable(.{
.name = "c_consumer",
.target = target,
.optimize = optimize,
});
c_exe.addCSourceFile(.{
.file = b.path("src/main.c"),
.flags = &.{"-std=c11"},
});
c_exe.linkLibrary(lib);
c_exe.linkLibC();
b.installArtifact(c_exe);zig
// 将Zig构建为兼容C的静态库
const lib = b.addStaticLibrary(.{
.name = "myzig",
.root_source_file = b.path("src/lib.zig"),
.target = target,
.optimize = optimize,
});
// 使用Zig库的C代码
const c_exe = b.addExecutable(.{
.name = "c_consumer",
.target = target,
.optimize = optimize,
});
c_exe.addCSourceFile(.{
.file = b.path("src/main.c"),
.flags = &.{"-std=c11"},
});
c_exe.linkLibrary(lib);
c_exe.linkLibC();
b.installArtifact(c_exe);8. Opaque types and forward declarations
8. 不透明类型与前向声明
zig
// Forward-declared C struct (opaque)
const FILE = opaque {};
extern fn fopen(path: [*:0]const u8, mode: [*:0]const u8) ?*FILE;
extern fn fclose(file: *FILE) c_int;
extern fn fprintf(file: *FILE, fmt: [*:0]const u8, ...) c_int;
// Opaque handle pattern
const MyHandle = opaque {};
extern fn lib_create() ?*MyHandle;
extern fn lib_destroy(h: *MyHandle) void;zig
// 前向声明的C结构体(不透明类型)
const FILE = opaque {};
extern fn fopen(path: [*:0]const u8, mode: [*:0]const u8) ?*FILE;
extern fn fclose(file: *FILE) c_int;
extern fn fprintf(file: *FILE, fmt: [*:0]const u8, ...) c_int;
// 不透明句柄模式
const MyHandle = opaque {};
extern fn lib_create() ?*MyHandle;
extern fn lib_destroy(h: *MyHandle) void;9. Variadic functions
9. 可变参数函数
zig
// Call variadic C functions using @call with variadic args
const c = @cImport(@cInclude("stdio.h"));
// printf works directly through @cImport
_ = c.printf("value: %d\n", @as(c_int, 42));
// For custom variadic C functions, use extern with ...
extern fn my_log(level: c_int, fmt: [*:0]const u8, ...) void;For translate-c output guide and C ABI types reference, see references/translate-c-guide.md.
zig
// 使用@call传递可变参数调用C的可变参数函数
const c = @cImport(@cInclude("stdio.h"));
// printf可通过@cImport直接使用
_ = c.printf("value: %d\n", @as(c_int, 42));
// 对于自定义的C可变参数函数,使用extern和...声明
extern fn my_log(level: c_int, fmt: [*:0]const u8, ...) void;关于translate-c输出指南和C ABI类型参考,请查看references/translate-c-guide.md。
Related skills
相关技能
- Use for
skills/zig/zig-compilerC compilation and basic Zig buildszig cc - Use for
skills/zig/zig-build-systemwith mixed C/Zig projectsbuild.zig - Use to verify symbol exports and ABI
skills/binaries/elf-inspection - Use for comparison with Rust's C FFI approach
skills/rust/rust-ffi
- 如需使用编译C代码和基础Zig构建,请使用
zig ccskills/zig/zig-compiler - 如需在中配置C/Zig混合项目,请使用
build.zigskills/zig/zig-build-system - 如需验证符号导出和ABI,请使用
skills/binaries/elf-inspection - 如需与Rust的C FFI方式对比,请使用
skills/rust/rust-ffi