| author | |
| committer | |
| log | b92fac329e73280ea5d49af675fea84e777b7f0a |
| tree | 647c64025db7bd7c5948f8d5493befdf566c0071 |
| parent | ecc54640243ba84ffa3656b73aa7dd6b53474462 |
| parent | 45d9d9f953df2167b35878ea02551d9c86ad8a0f |
| signature |
3 files changed, 103 insertions(+), 13 deletions(-)
doc/langref.html.in+55| ... | @@ -7057,6 +7057,61 @@ const c = @cImport({ | ... | @@ -7057,6 +7057,61 @@ const c = @cImport({ |
| 7057 | }); | 7057 | }); |
| 7058 | {#code_end#} | 7058 | {#code_end#} |
| 7059 | {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#} | 7059 | {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#} |
| 7060 | {#header_close#} | ||
| 7061 | {#header_open|Exporting a C Library#} | ||
| 7062 | <p> | ||
| 7063 | One of the primary use cases for Zig is exporting a library with the C ABI for other programming languages | ||
| 7064 | to call into. The <code>export</code> keyword in front of functions, variables, and types causes them to | ||
| 7065 | be part of the library API: | ||
| 7066 | </p> | ||
| 7067 | <p class="file">mathtest.zig</p> | ||
| 7068 | {#code_begin|syntax#} | ||
| 7069 | export fn add(a: i32, b: i32) i32 { | ||
| 7070 | return a + b; | ||
| 7071 | } | ||
| 7072 | {#code_end#} | ||
| 7073 | <p>To make a shared library:</p> | ||
| 7074 | <pre><code class="shell">$ zig build-lib mathtest.zig | ||
| 7075 | </code></pre> | ||
| 7076 | <p>To make a static library:</p> | ||
| 7077 | <pre><code class="shell">$ zig build-lib mathtest.zig --static | ||
| 7078 | </code></pre> | ||
| 7079 | <p>Here is an example with the {#link|Zig Build System#}:</p> | ||
| 7080 | <p class="file">test.c</p> | ||
| 7081 | <pre><code class="cpp">// This header is generated by zig from mathtest.zig | ||
| 7082 | #include "mathtest.h" | ||
| 7083 | #include &lt;assert.h&gt; | ||
| 7084 | |||
| 7085 | int main(int argc, char **argv) { | ||
| 7086 | assert(add(42, 1337) == 1379); | ||
| 7087 | return 0; | ||
| 7088 | }</code></pre> | ||
| 7089 | <p class="file">build.zig</p> | ||
| 7090 | {#code_begin|syntax#} | ||
| 7091 | const Builder = @import("std").build.Builder; | ||
| 7092 | |||
| 7093 | pub fn build(b: *Builder) void { | ||
| 7094 | const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0)); | ||
| 7095 | |||
| 7096 | const exe = b.addCExecutable("test"); | ||
| 7097 | exe.addCompileFlags([][]const u8{"-std=c99"}); | ||
| 7098 | exe.addSourceFile("test.c"); | ||
| 7099 | exe.linkLibrary(lib); | ||
| 7100 | |||
| 7101 | b.default_step.dependOn(&exe.step); | ||
| 7102 | |||
| 7103 | const run_cmd = b.addCommand(".", b.env_map, [][]const u8{exe.getOutputPath()}); | ||
| 7104 | run_cmd.step.dependOn(&exe.step); | ||
| 7105 | |||
| 7106 | const test_step = b.step("test", "Test the program"); | ||
| 7107 | test_step.dependOn(&run_cmd.step); | ||
| 7108 | } | ||
| 7109 | {#code_end#} | ||
| 7110 | <p class="file">terminal</p> | ||
| 7111 | <pre><code class="shell">$ zig build | ||
| 7112 | $ ./test | ||
| 7113 | $ echo $? | ||
| 7114 | 0</code></pre> | ||
| 7060 | {#header_close#} | 7115 | {#header_close#} |
| 7061 | {#header_open|Mixing Object Files#} | 7116 | {#header_open|Mixing Object Files#} |
| 7062 | <p> | 7117 | <p> |
src/ir.cpp+16-4| ... | @@ -60,7 +60,7 @@ enum ConstCastResultId { | ... | @@ -60,7 +60,7 @@ enum ConstCastResultId { |
| 60 | ConstCastResultIdType, | 60 | ConstCastResultIdType, |
| 61 | ConstCastResultIdUnresolvedInferredErrSet, | 61 | ConstCastResultIdUnresolvedInferredErrSet, |
| 62 | ConstCastResultIdAsyncAllocatorType, | 62 | ConstCastResultIdAsyncAllocatorType, |
| 63 | ConstCastResultIdNullWrapPtr, | 63 | ConstCastResultIdNullWrapPtr |
| 64 | }; | 64 | }; |
| 65 | 65 | ||
| 66 | struct ConstCastOnly; | 66 | struct ConstCastOnly; |
| ... | @@ -8471,9 +8471,9 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry | ... | @@ -8471,9 +8471,9 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry |
| 8471 | if (wanted_type == actual_type) | 8471 | if (wanted_type == actual_type) |
| 8472 | return result; | 8472 | return result; |
| 8473 | 8473 | ||
| 8474 | // * and [*] can do a const-cast-only to ?* and ?[*], respectively | 8474 | // *T and [*]T may const-cast-only to ?*U and ?[*]U, respectively |
| 8475 | // but not if there is a mutable parent pointer | 8475 | // but not if we want a mutable pointer |
| 8476 | // and not if the pointer is zero bits | 8476 | // and not if the actual pointer has zero bits |
| 8477 | if (!wanted_is_mutable && wanted_type->id == TypeTableEntryIdOptional && | 8477 | if (!wanted_is_mutable && wanted_type->id == TypeTableEntryIdOptional && |
| 8478 | wanted_type->data.maybe.child_type->id == TypeTableEntryIdPointer && | 8478 | wanted_type->data.maybe.child_type->id == TypeTableEntryIdPointer && |
| 8479 | actual_type->id == TypeTableEntryIdPointer && type_has_bits(actual_type)) | 8479 | actual_type->id == TypeTableEntryIdPointer && type_has_bits(actual_type)) |
| ... | @@ -8488,6 +8488,18 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry | ... | @@ -8488,6 +8488,18 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry |
| 8488 | return result; | 8488 | return result; |
| 8489 | } | 8489 | } |
| 8490 | 8490 | ||
| 8491 | // *T and [*]T can always cast to *c_void | ||
| 8492 | if (wanted_type->id == TypeTableEntryIdPointer && | ||
| 8493 | wanted_type->data.pointer.ptr_len == PtrLenSingle && | ||
| 8494 | wanted_type->data.pointer.child_type == g->builtin_types.entry_c_void && | ||
| 8495 | actual_type->id == TypeTableEntryIdPointer && | ||
| 8496 | (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) && | ||
| 8497 | (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile)) | ||
| 8498 | { | ||
| 8499 | assert(actual_type->data.pointer.alignment >= wanted_type->data.pointer.alignment); | ||
| 8500 | return result; | ||
| 8501 | } | ||
| 8502 | |||
| 8491 | // pointer const | 8503 | // pointer const |
| 8492 | if (wanted_type->id == TypeTableEntryIdPointer && actual_type->id == TypeTableEntryIdPointer) { | 8504 | if (wanted_type->id == TypeTableEntryIdPointer && actual_type->id == TypeTableEntryIdPointer) { |
| 8493 | ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type, | 8505 | ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type, |
test/cases/cast.zig+32-9| ... | @@ -487,12 +487,35 @@ fn MakeType(comptime T: type) type { | ... | @@ -487,12 +487,35 @@ fn MakeType(comptime T: type) type { |
| 487 | } | 487 | } |
| 488 | 488 | ||
| 489 | test "implicit cast from *[N]T to ?[*]T" { | 489 | test "implicit cast from *[N]T to ?[*]T" { |
| 490 | var x: ?[*]u16 = null; | ||
| 491 | var y: [4]u16 = [4]u16 {0, 1, 2, 3}; | ||
| 492 | |||
| 493 | x = &y; | ||
| 494 | assert(std.mem.eql(u16, x.?[0..4], y[0..4])); | ||
| 495 | x.?[0] = 8; | ||
| 496 | y[3] = 6; | ||
| 497 | assert(std.mem.eql(u16, x.?[0..4], y[0..4])); | ||
| 498 | } | ||
| \ No newline at end of file | |||
| 490 | var x: ?[*]u16 = null; | ||
| 491 | var y: [4]u16 = [4]u16{ 0, 1, 2, 3 }; | ||
| 492 | |||
| 493 | x = &y; | ||
| 494 | assert(std.mem.eql(u16, x.?[0..4], y[0..4])); | ||
| 495 | x.?[0] = 8; | ||
| 496 | y[3] = 6; | ||
| 497 | assert(std.mem.eql(u16, x.?[0..4], y[0..4])); | ||
| 498 | } | ||
| 499 | |||
| 500 | test "implicit cast from *T to ?*c_void" { | ||
| 501 | var a: u8 = 1; | ||
| 502 | incrementVoidPtrValue(&a); | ||
| 503 | std.debug.assert(a == 2); | ||
| 504 | } | ||
| 505 | |||
| 506 | fn incrementVoidPtrValue(value: ?*c_void) void { | ||
| 507 | @ptrCast(*u8, value.?).* += 1; | ||
| 508 | } | ||
| 509 | |||
| 510 | test "implicit cast from [*]T to ?*c_void" { | ||
| 511 | var a = []u8{ 3, 2, 1 }; | ||
| 512 | incrementVoidPtrArray(a[0..].ptr, 3); | ||
| 513 | assert(std.mem.eql(u8, a, []u8{ 4, 3, 2 })); | ||
| 514 | } | ||
| 515 | |||
| 516 | fn incrementVoidPtrArray(array: ?*c_void, len: usize) void { | ||
| 517 | var n: usize = 0; | ||
| 518 | while (n < len) : (n += 1) { | ||
| 519 | @ptrCast([*]u8, array.?)[n] += 1; | ||
| 520 | } | ||
| 521 | } | ||