#How to properly cast external C data types? (shared library on linux)

1 messages · Page 1 of 1 (latest)

slim patrol
#

Hi, this is my first experience with Ziglang, so probably some kind of noob question.
With that said, I'm hacking together a shared library and have some trouble to cast the C data types probably in Zig.

I'm trying to replicate this C code

int statusengine_handle_data(int event_type, void *data){
    servicecheck = (nebstruct_service_check_data *)data;

This is my Zig attempt:

pub fn handle_service_check_data(event_type: c_int, data: ?*anyopaque) callconv(.C) c_int {
    var service_check = @as(?*naemon.nebstruct_service_check_data, @alignCast(data.?));

    _ = event_type;
    naemon.nm_log(naemon.NSLOG_RUNTIME_ERROR, "Got service check from service:  '%s'!", service_check.service_description);
    return 0;
}

My issue now is, that I don't find the correct syntax to cast the data: ?*anyopaque into a ?*naemon.nebstruct_service_check_data

That's my error message

src/main.zig:36:68: error: pointer element type 'anyopaque' cannot coerce into element type 'naemon.struct_nebstruct_service_check_struct'
    var service_check = @as(?*naemon.nebstruct_service_check_data, @alignCast(data.?));
                                                                   ^~~~~~~~~~~~~~~~~~
src/naemon.zig:7879:58: note: struct declared here
pub const struct_nebstruct_service_check_struct = extern struct {
                                                  ~~~~~~~^~~~~~
src/main.zig:36:68: note: use @ptrCast to cast pointer element type
red musk
#

var service_check: ?*naemon.nebstruct_service_check_data = @ptrCast(@alignCast(data));

#

@as is for coercion e.g. u16 to u32. it doesnt cast

slim patrol
#

Perfect, thanks I will give it a shot!

slim patrol
#

The good new is, that the cast is working!

I'm now getting this as new error:

src/main.zig:39:47: error: type '?*naemon.struct_nebstruct_service_check_struct' does not support field access
    const service_description = ?service_check.service_description;

I'm trying to unwrap the field like so

var service_check: ?*naemon.nebstruct_service_check_data = @ptrCast(@alignCast(data));
const service_description = ?service_check.service_description;
red musk
#

thats because its an optional type, it may be null. if you can guarantee that its not null you can do service_check.?.service_description but doing this on a null pointer will panic or segfault depending on the build mode

#

if you cant guarantee its not null youll have to check manually

if (service_check) |sc| { // sc is a guaranteed non null type and doesnt require the .? syntax
  sc.service_description ...
} else { // if service_check is null
...
}
slim patrol
#

That looks like to way to go, thanks again!

red musk
#

np

slim patrol
#

Interessting, if i try to print the value, i run into an Segmentation fault in mem.zig:

std.debug.print("Service: {s}", .{sc.service_description});
heavy vine
#

Not sure what the type of that field is, but if it's a C-string, consider using std.mem.sliceTo.