zig/test/behavior/extern.zig
2025-10-02 17:44:52 -04:00

69 lines
2 KiB
Zig

const builtin = @import("builtin");
const std = @import("std");
const expect = std.testing.expect;
test "anyopaque extern symbol" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const a = @extern(*anyopaque, .{ .name = "a_mystery_symbol" });
const b: *i32 = @ptrCast(@alignCast(a));
try expect(b.* == 1234);
}
export var a_mystery_symbol: i32 = 1234;
test "function extern symbol" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const a = @extern(*const fn () callconv(.c) i32, .{ .name = "a_mystery_function" });
try expect(a() == 4567);
}
export fn a_mystery_function() i32 {
return 4567;
}
test "function extern symbol matches extern decl" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
extern fn another_mystery_function() u32;
const same_thing = @extern(*const fn () callconv(.c) u32, .{ .name = "another_mystery_function" });
};
try expect(S.another_mystery_function() == 12345);
try expect(S.same_thing() == 12345);
}
export fn another_mystery_function() u32 {
return 12345;
}
extern fn c_extern_function() [*c]u32;
test "coerce extern function types" {
const S = struct {
export fn c_extern_function() [*c]u32 {
return null;
}
};
_ = S;
_ = @as(fn () callconv(.c) ?*u32, c_extern_function);
}
fn a_function(func: fn () callconv(.c) void) void {
_ = func;
}
test "pass extern function to function" {
a_function(struct {
extern fn an_extern_function() void;
}.an_extern_function);
a_function(@extern(*const fn () callconv(.c) void, .{ .name = "an_extern_function" }).*);
}
export fn an_extern_function() void {}