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