Merge pull request #183 from chrboesch/hello_c

added the first C exercise
This commit is contained in:
Chris Boesch 2023-02-16 19:42:24 +01:00 committed by GitHub
commit 5d7d811298
3 changed files with 86 additions and 0 deletions

View file

@ -31,6 +31,10 @@ const Exercise = struct {
/// We need to keep track of this, so we compile without the self hosted compiler /// We need to keep track of this, so we compile without the self hosted compiler
@"async": bool = false, @"async": bool = false,
/// This exercise makes use of C functions
/// We need to keep track of this, so we compile with libc
C: bool = false,
/// Returns the name of the main file with .zig stripped. /// Returns the name of the main file with .zig stripped.
pub fn baseName(self: Exercise) []const u8 { pub fn baseName(self: Exercise) []const u8 {
assert(std.mem.endsWith(u8, self.main_file, ".zig")); assert(std.mem.endsWith(u8, self.main_file, ".zig"));
@ -465,6 +469,11 @@ const exercises = [_]Exercise{
.main_file = "092_interfaces.zig", .main_file = "092_interfaces.zig",
.output = "Daily Insect Report:\nAnt is alive.\nBee visited 17 flowers.\nGrasshopper hopped 32 meters.", .output = "Daily Insect Report:\nAnt is alive.\nBee visited 17 flowers.\nGrasshopper hopped 32 meters.",
}, },
.{
.main_file = "093_hello_c.zig",
.output = "Hello C from Zig! - C result ist 17 chars",
.C = true,
},
.{ .{
.main_file = "999_the_end.zig", .main_file = "999_the_end.zig",
.output = "\nThis is the end for now!\nWe hope you had fun and were able to learn a lot, so visit us again when the next exercises are available.", .output = "\nThis is the end for now!\nWe hope you had fun and were able to learn a lot, so visit us again when the next exercises are available.",
@ -729,6 +738,11 @@ const ZiglingStep = struct {
// zig_args.append("-fstage1") catch unreachable; // zig_args.append("-fstage1") catch unreachable;
// } // }
// Enable C support for exercises that use C functions
if (self.exercise.C) {
zig_args.append("-lc") catch unreachable;
}
if (builder.color != .auto) { if (builder.color != .auto) {
zig_args.append("--color") catch unreachable; zig_args.append("--color") catch unreachable;
zig_args.append(@tagName(builder.color)) catch unreachable; zig_args.append(@tagName(builder.color)) catch unreachable;

68
exercises/093_hello_c.zig Normal file
View file

@ -0,0 +1,68 @@
//
// When Andrew Kelley announced the idea of a new programming language
// - namely Zig - in his blog on February 8, 2016, he also immediately
// stated his ambitious goal: to replace the C language!
//
// In order to be able to achieve this goal at all, Zig should be
// as compatible as possible with its "predecessor".
// Only if it is possible to exchange individual modules in existing
// C programs without having to use complicated wrappers,
// the undertaking has a chance of success.
//
// So it is not surprising that calling C functions and vice versa
// is extremely "smooth".
//
// To call C functions in Zig, you only need to specify the library
// that contains said function. For this purpose there is a built-in
// function corresponding to the well-known @import():
//
// @cImport()
//
// All required libraries can now be included in the usual Zig notation:
//
// const c = @cImport({
// @cInclude("stdio.h");
// @cInclude("...");
// });
//
// Now a function can be called via the (in this example) constant 'c':
//
// c.puts("Hello world!");
//
// By the way, most C functions have return values in the form of an
// integer value. Errors can then be evaluated (return < 0) or other
// information can be obtained. For example, 'puts' returns the number
// of characters output.
//
// So that all this does not remain a dry theroy now, let's just start
// and call a C function out of Zig.
// our well-known "import" for Zig
const std = @import("std");
// and here the new the import for C
const c = @cImport({
@cInclude("unistd.h");
});
pub fn main() void {
// In order to output a text that can be evaluated by the
// Zig Builder, we need to write it to the Error output.
// In Zig we do this with "std.debug.print" and in C we can
// specify a file descriptor i.e. 2 for error console.
//
// In this exercise we use 'write' to output 17 chars,
// but something is missing...
const c_res = write(2, "Hello C from Zig!", 17);
// let's see what the result from C is:
std.debug.print(" - C result ist {d} chars\n", .{c_res});
}
//
// Something must be considered when compiling with C functions.
// Namely that the Zig compiler knows that it should include
// corresponding libraries. For this purpose we call the compiler
// with the parameter "lc" for such a program,
// e.g. "zig run -lc hello_c.zig".
//

View file

@ -0,0 +1,4 @@
57c57
< const c_res = write(2, "Hello C from Zig!", 17);
---
> const c_res = c.write(2, "Hello C from Zig!", 17);