#Beginner dynamic dispatch questions

1 messages · Page 1 of 1 (latest)

sour nimbus
#

I'm new to zig, coming from C/C++. I wrote a basic dynamic interface using function pointers:

  • Is there a more 'zig' way of solving this problem?

  • Is my use of opaque pointers and @ptrCast appropriate?

#

Also, I prefixed some struct fields with _ as you do in python to show they are not public, is there an established way to do this in zig?

hexed ember
dusky bobcat
hexed ember
#

Looking at your impl, looks entirely okay for me. Maybe I'd wrap overrided functions in a struct but that's only the matter of organizing self-contained code.

sour nimbus
#

Awesome, thanks for the help!

hexed ember
#

As pachde wrote, underscore isn't really used as a standard. You can infer if field is public if it has a docstring (at least that's how std does it I reckon).

dusky bobcat
hexed ember
#

Ah, yeah, should've communicated that clearer. I'm too new in the community so I trust your judgement more.

smoky crane
#

A doc comment saying you probably shouldn’t touch it is what I do

lyric sable
#

In your read_byte() and write_byte() self can be self: Source. No need for a pointer. Zig isn't like C, it will automatically generate code to pass by reference if the struct size is large or pass by value if the struct size is small. Took me some time to figure this out, coming from C/C++ as well.

You really only need *Source if:

  1. you intend to modify it's values.
  2. you intend to store the pointer in some long lived data structure so therefore require the reference.

Otherwise just use self: Source.

Here is an example:

const std = @import("std");
const expect = std.testing.expect;

// This is a structure that has 100 bytes of data.
const BigStruct = struct {
    // Initialize to zeroes.
    data: [100]u8 = [1]u8{0} ** 100,

    // No need for pointer. The compiler will auto generate code to pass by value 
    // or ref depending on size.
    // In this case it will pass by ref (ptr) because data is 100 bytes
    // Note that self is const. We cannot modify it's contents.
    //
    fn get(self: BigStruct, pos: usize) u8 {
        return self.data[pos];
    }

    // When we want to modify the contents, we use explicit pointer.
    // 
    fn set(self: *BigStruct, pos: usize, val: u8) void {
        self.data[pos] = val;
    }

    // This will not compile.
    // Parameter value is constant. Zig will not let us modify the data.
    //
    fn clear(self: BigStruct) void {
        @memset(&self.data, 0);
    }
};

test "test" {
    var data = BigStruct { };
    data.set(0, 0xff);

    try expect(data.get(0)==0xff);

    // Uncomment this will error in clear():
    // error: cannot memset constant pointer
    // data.clear();
}
quaint jewel
quaint jewel
lyric sable