I’m trying to call int SDL_LockTexture(SDL_Texture*, SDL_Rect*, void**, int*)from Zig.
cImport is generating:
pub extern fn SDL_LockTexture(texture: ?*SDL_Texture, rect: [*c]const SDL_Rect, pixels: [*c]?*anyopaque, pitch: [*c]c_int) c_int;
The API of this function is such that my code should assign values in the void** array using the int* value as a pitch-offset in bytes.
With the following code:
const pixels: [*c]?*anyopaque = undefined;
const maybe_pitch: [*c]c_int = null;
const result = sdl.SDL_LockTexture(texture, undefined, pixels, maybe_pitch);
We get an address bounds exception at run-time, I presume due to the address of pixels? Reading the documentation on ziglang, it’s recommended to avoid [*c] types… what’s the right way to do this?
1 Like
According to the documentation, pixels and pitch are out parameters, SDL wants to write to them, so by passing undefined or null, you get an error.
Instead what you usually want to do is put them on the stack and pass a reference to them like so:
const pixels: ?*anyopaque = undefined;
const pitch: c_int = undefined;
const result = sdl.SDL_LockTexture(texture, null, &pixels, &pitch);
Also the second parameter expects a valid pointer or null, passing undefined will also cause problems, you probably want to pass null.
1 Like
This is what’s confusing me, I tried this code:
const pixels: ?*anyopaque = undefined;
const pitch: c_int = undefined;
std.debug.print("render before lock\n", .{});
const locked = sdl.SDL_LockTexture(texture, null, &pixels, &pitch);
and Zig replies with:
+- compile exe zig8 Debug native 1 errors
src/main.zig:329:55: error: expected type '[*c]?*anyopaque', found '*const ?*anyopaque'
const locked = sdl.SDL_LockTexture(texture, null, &pixels, &maybe_pitch);
^~~~~~~
src/main.zig:329:55: note: cast discards const qualifier
.zig-cache/o/a579793575bede4e8e421be4fe991389/cimport.zig:35475:89: note: parameter type declared here
pub extern fn SDL_LockTexture(texture: ?*SDL_Texture, rect: [*c]const SDL_Rect, pixels: [*c]?*anyopaque, pitch: [*c]c_int) c_int;
^~~~~~~~~~~~~~~
agentultra:
const pixels: ?*anyopaque = undefined;
const pitch: c_int = undefined;
std.debug.print("render before lock\n", .{});
const locked = sdl.SDL_LockTexture(texture, null, &pixels, &pitch);
var pixels: ?*anyopaque = undefined;
var pitch: c_int = undefined;
std.debug.print("render before lock\n", .{});
const locked = sdl.SDL_LockTexture(texture, null, &pixels, &pitch);
Marvelous. The error from const/var is quite confusing.
So is this the standard way to handle out vars from C APIs where you’re expected to mutate the void** value?