PCSC sample in Zig
I continue the list of PC/SC wrappers I started in 2010 with PC/SC sample in different languages. I am now presenting a new sample code in Zig.
pcsc-z
The wrapper is available at https://github.com/kofi-q/pcsc-z and is compatible for GNU/Linux, macOS and Windows.
The author is kofi-q.
The licence is MIT.
The API documentation can be found at https://kofi-q.github.io/pcsc-z/#pcsc.
Zig
From Wikipedia Zig article:
Zig is a system programming language designed to be a general-purpose improvement to the C programming language. It is free and open-source software, released under an MIT License.
Differences with C relate to control flow, function calls, library imports, variable declaration and Unicode support. The language makes no use of macros or preprocessor instructions. Features adopted from modern languages include the addition of compile time generic programming data types, allowing functions to work on a variety of data, along with a small set of new compiler directives to allow access to the information about those types using reflection. Zig requires manual memory management, but attempts to improve memory safety through option types and a unit testing framework. Features for low-level programming include packed structs, arbitrary-width integers and multiple pointer types.
Zig was designed by Andrew Kelly and first announced in 2016. Development is funded by the Zig Software Foundation (ZSF).
Installation
I had to use an older version of the Zig-PC/SC wrapper because I used Zig 0.15.2 (stable version) instead of the development version 0.16.
Source code
To get started, you can use the zig init command to generate a
minimal zig project.
$ zig init info: created build.zig info: created build.zig.zon info: created src/main.zig info: created src/root.zig info: see `zig build --help` for a menu of options
You then need to update 2 files: src/main.zig and build.zig.
//! src/main.zig const std = @import("std"); const pcsc = @import("pcsc"); pub fn main() !void { const client = try pcsc.Client.init(.SYSTEM); defer client.deinit() catch |err| std.debug.print( "Unable to release client: {t}", .{err}, ); // Connect to 1st reader var reader_names = try client.readerNames(); if (reader_names.next()) |reader_name| { std.debug.print("Using: {s}\n", .{reader_name}); // Connect to an inserted card: const card = try client.connect(reader_name, .SHARED, .ANY); defer card.disconnect(.LEAVE) catch |err| std.debug.print( "Unable to disconnect card: {t}\n", .{err}, ); std.debug.print("Card connected with protocol {f}\n", .{card.protocol}); var buf_response: [pcsc.max_buffer_len]u8 = undefined; // SELECT command const select = [_]u8{ 0x00, 0xA4, 0x04, 0x00, 0x0A, 0xA0, 0x00, 0x00, 0x00, 0x62, 0x03, 0x01, 0x0C, 0x06, 0x01 }; std.debug.print("Transmitting APDU: {x}\n", .{select}); var response = try card.transmit(&select, &buf_response); std.debug.print("Received response: {x}\n", .{response}); // TEST command const command = [_]u8{ 0x00, 0x00, 0x00, 0x00 }; std.debug.print("Transmitting APDU: {x}\n", .{command}); response = try card.transmit(&command, &buf_response); std.debug.print("Received response: {x}\n", .{response}); // Truncate the 2 last bytes: status word const text = response[0..response.len-2]; std.debug.print("Text: {s}\n", .{text}); } else { std.debug.print("No reader found\n", .{}); } }
//! build.zig const std = @import("std"); pub fn build(b: *std.Build) !void { const target = b.standardTargetOptions(.{}); const mode = b.standardOptimizeOption(.{}); const pcsc_dep = b.dependency("pcsc", .{ .optimize = mode, .target = target, }); const pcsc_mod = pcsc_dep.module("pcsc"); const exe = b.addExecutable(.{ .name = "pcsc-demo", .root_module = b.createModule(.{ .imports = &.{ .{ .name = "pcsc", .module = pcsc_mod }, }, .optimize = mode, .root_source_file = b.path("src/main.zig"), .target = target, }), }); const demo_run = b.addRunArtifact(exe); const demo_step = b.step("demo", "Run PCSC demo"); demo_step.dependOn(&demo_run.step); }
Output
Conclusion
Zig is a relatively new programming language. We can already find a PC/SC wrapper for it. That is great!
If you are working on a Free Software PC/SC wrapper that is not yet on my list please let me know.




