簡體   English   中英

訪問 Zig 0.7.0 中 C 函數按值返回的結構

[英]Access Structs Returned by Value from C Functions in Zig 0.7.0

這是一些 C 代碼,我通過 linux-x86_64 上的 @cImport 在 Zig 0.7.0 中導入到 Zig。 當我在 Zig 中直接創建一個struct Point結構時,它按預期工作,但是當我從getPoint方法按值返回一個時,有錯誤的數據(參見下面的“輸出”)。 我做錯了什么,還是這是一個錯誤?

  • 點.h

    struct Point {
        int x;
        int y;
        int z;
    };
    
    struct Point getPoint(void);
  • 點.c

    #include "point.h"
    #include <stdio.h>
    
    struct Point getPoint() {
        struct Point retVal = { .x=50, .y=50, .z=50 };
        return retVal;
    }

  • 主要的.zig

    const std = @import("std");
    const c = @cImport({
        @cInclude("point.h");
    });
    
    pub fn main() void {
        var point = c.getPoint();
        var anotherPoint = c.Point{ .x = 50, .y = 50, .z = 50 };
        std.debug.print("point x: {} y: {} z: {}\n", .{ point.x, point.y, point.z });
        std.debug.print("anotherPoint x: {} y: {} z: {}\n", .{ anotherPoint.x, anotherPoint.y, anotherPoint.z });
    }

  • output

    point x: 50 y: 50 z: -1705967616
    anotherPoint x: 50 y: 50 z: 50
  • 構建.zig

    const Builder = @import("std").build.Builder;
    
    pub fn build(b: *Builder) void {
        // Standard target options allows the person running `zig build` to choose
        // what target to build for. Here we do not override the defaults, which
        // means any target is allowed, and the default is native. Other options
        // for restricting supported target set are available.
        const target = b.standardTargetOptions(.{});
        //const lib = b.addStaticLibrary("interface", "src/libinterface.a");
    
        // Standard release options allow the person running `zig build` to select
        // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
        const mode = b.standardReleaseOptions();
    
        const exe = b.addExecutable("point_test", "src/main.zig");
        exe.setTarget(target);
        exe.setBuildMode(mode);
        exe.linkLibC();
        exe.addIncludeDir("src");
        exe.install();
        exe.addCSourceFile("src/point.c", &[_][]const u8{
            "-Wall",
            "-Wextra",
            "-Werror",
        });
    
        const run_cmd = exe.run();
        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);
    }

Zig 的 c abi 兼容性目前在結構和浮點數方面存在一些問題。

您遇到的具體問題#3211已得到修復,您的代碼現在可以工作了。

$> zig run main.zig point.c -I.
point x: 50 y: 50 z: 50
anotherPoint x: 50 y: 50 z: 50

但是,C abi 互操作仍然存在問題,例如: #9487

在解決所有這些問題之前,通常可以通過使用指針而不是 arguments 的值傳遞和返回值來解決它

// workaround.h

#include "point.h"

void workaround_getPoint(struct Point* out);
// workaround.c

#include "workaround.h"

void workaround_getPoint(struct Point* out) {
    *out = getPoint();
}
// .zig
const c = @cImport({
    @cInclude("point.h");
    @cInclude("workaround.h");
});
pub fn getPoint(): c.Point {
    var res: c.Point = undefined;
    c.workaround_getPoint(&res);
    return res;
}
// build.zig
        exe.addCSourceFile("src/workaround.c", &.{ "-Wall", "-Wextra", "-Werror" });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM