Hi,
I have a question regarding the address of a constant array. I am writing a WASM module that simply returns a string.
// The actual string I want to return
const name: []const u8 = "huntrss";
// An array that contains the address to the string and it length
// The WASM runtime I use will later read from this array to get the address and length
// of the string
var return_value: [2]i32 = [_]i32{0} ** 2;
pub export fn name() callconv(.C) i32 {
const name_address = @intCast(i32, @ptrToInt(&name));
return_value[0] = name_address;
const name_length = @intCast(i32, name.len);
return_value[1] = name_length;
// The following lines I do not fully understand, but I trial-an-errored them:
// Get the address to the first element of the return_value address
const ptr_to_return_value: *i32 = &return_value[0];
// Dereference the pointer to get the "actual" address of return_value
const ptr = @intCast(i32, ptr_to_return_value.*);
return ptr;
}
So what I don’t understand, as mentioned above is, why I need to dereference the pointer again to get the address. I could debug the resulting WASM module and I indentified that the wrong address was returned. That’s why I came up with the idea to dereference it again.
Can someone explain to me, why I need to dereference the pointer, please?
Thanks in advance
Edit:
I am using zig version 0.10.1.
2 Likes
I’m curious if you have tried other built-ins, such as @intFromPtr?
The documentation isn’t as clear as I’d like it to be, but it may be worth checking out:
@intFromPtr:
Converts value to a usize which is the address of the pointer. value can be *T or ?*T.
To convert the other way, use @ptrFromInt
I’m running this code here:
var return_value: [2]i32 = [_]i32{0} ** 2;
const print = @import("std").debug.print;
pub fn main() !void
{
const p1: *i32 = &return_value[0];
const p2: *[2]i32 = &return_value;
print("\n\n{any}\n\n{any}\n\n", .{@intCast(i32, @intFromPtr(p1)), @intCast(i32, @intFromPtr(p2))});
}
And here is what it produces:
2416648
2416648
Just a note - here in, @intCast is changing so that the first argument will not be necessary: Major zig language update just landed: removal of destination type from all cast builtins - #4 by AndrewCodeDev
1 Like
Thanks for the reply. I did not know about @intFromPtr. However I forgot to mention that I am using 0.10.1 where it is not available. I will check the implementation of @intFromPtr in the zig master version to find how it is implemented.
I think I see the problem. The original type of that string literal is *[7:0]const u8. By defining name to be a slice, you case the pointer to coerce to a slice value. A slice is its own chunk of memory that holds both pointer and length (same as what you’re doing explicitly with return_value).
In this line you’re taking the pointer of the slice, which is not what you want. To obtain the underlying pointer that the slice refers to you have to do name.ptr.
I think from there you will be able to fix the rest of the program to obtain what you want.
2 Likes
That does the trick. Thanks @kristoff.
1 Like