aboutsummaryrefslogtreecommitdiff
path: root/test/behavior/extern.zig
blob: 4de68589468790419a9e993fd68caf2f20e6eae9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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 {}