#how do modules work in zig?

1 messages · Page 1 of 1 (latest)

ember shell
#

So i haven't found any good resources on how to make code modular in zig. To give more context my primary experience is with c/c++ where i can split code into header and source files like include/foo.hpp and src/foo.cpp and compile them along with src/main.cpp (im not talking about c++20 modules just to be clear). So how to achieve something similar in zig?

remote wren
#

Zig double-purposes structs to stand in for namespaces. suppose you have a definition like so:

const foo = struct {
    fn bar() void { ... }
};
```to call `bar` from outside the type definition, you'll have to write `foo.bar()`  - this is the basic idea of namespacing.

in Zig, each file is also secretly a `struct` definition, you can even have it have fields (see, for example, the file [`std/mem/Allocator.zig`](https://ziglang.org/documentation/master/std/#src/std/mem/Allocator.zig)) - importing a file is as if you've declared some `struct` type, and gave it a name (except that importing the same file twice gives two referrals to the same definition):
```ts
// this...
const std = @import("std");

// ...is kinda like this
const std = struct { ... };

anyhow, to organise your code into different namespaces, simply define different parts in different files, the import mechanism will naturally lead you to prefix identifiers which are defined in other files

ember shell
#

hmm

#

so how do i do it at a file levle?

#

lets say i wanna create a simple abstraction for a file

remote wren
#

what does "abstraction" mean in this context?

ember shell
#

well a struct containing data related to a file and functions for file related stuff

#

like file.open(), file.bytes etc.

#

probably like this:

#
#pragma once

#include <cstddef>
#include <filesystem>
#include <fstream>
#include <span>
#include <vector>

class File {
public:
  static File load(const std::filesystem::path &path);
  const std::filesystem::path path() const { return m_path; }
  const std::span<std::byte> bytes() { return m_bytes; }

private:
  std::fstream m_file{};
  std::vector<std::byte> m_bytes{};
  std::filesystem::path m_path{};
  size_t m_file_size{};
};
#

and file.cpp to contain any implementations

#

how do i organize my zig code like this

#

if that makes sense

remote wren
# ember shell and `file.cpp` to contain any implementations

Zig does not distinguish header files from source files - you needn't write your definitions twice, once in a header, and once in source. functions and constants which should be available for use from other files are marked pub, all else will just not be accessible from other files, enforced by the compiler

ember shell
#

yes yes i understood that part, regarding not having separate declaration and source files

#

so should it be something like this:

.
├── a.txt
├── b.txt
├── build.zig
├── src
│   └── main.zig
└── zig-out
    └── bin
        └── main

and i just add file.zig in src/?

#

and modify build.zig to accommodate that?

remote wren
#

and i just add file.zig in src/?
yes, this sounds reasonable - or perhaps in some sub-directory, if the whole directory's contents is related

quasi patio
#

It may be instructive to note that source code organization, even if you use modules, all compile to the same translation unit.

remote wren
ember shell
#

ohh yeah right!

quasi patio
ember shell
#

hmm makes sense, i can also do it for maintainability/readability right?

quasi patio
#

sure

ember shell
#

understandable, thank you!

gray fox
#

Zig is a single compilation unit language -- C/C++ are not. It's a mistakesub-optimal to apply C/C++ modularization concepts to Zig.

proven slate
#

shameless self plug but I tried my best to make a modular project in this series:
https://www.youtube.com/watch?v=utsQcEyvf60&list=PLlKj-4rp1Gz1WV7Lry7heAngUTBMEXJQL

Building a Media Player in Zig: The Modular Setup (SDL3 & FFmpeg)
Discord: https://discord.codotaku.com
Code: https://github.com/CodesOtakuYT/codotaku_media_player/tree/4ceb106726bda111c1c7b70b726154a348b6014b

Zig is an in-development imperative, general-purpose, statically typed, compiled system programming language designed by Andrew Kelley. ...

▶ Play video
quasi patio
proven slate