zig
zig copied to clipboard
cimport cannot cast NULL into optional function pointer
zig version: 0.12.0
install
└─ install main
└─ zig build-exe main Debug native 1 errors
xxx\zig-cache\o\762541bc2d17073d70cb6792c5fbd54b\cimport.zig:90966:293: error: expected type '?*const fn (?*cimport.struct__LIBSSH2_SESSION, [*c][*c]u8, [*c]c_int, [*c]?*anyopaque) callconv(.C) void', found '?*anyopaque'
pub inline fn libssh2_userauth_password(session: anytype, username: anytype, password: anytype) @TypeOf(libssh2_userauth_password_ex(session, username, @import("std").zig.c_translation.cast(c_uint, strlen(username)), password, @import("std").zig.c_translation.cast(c_uint, strlen(password)), NULL)) {
^~~~
xxx\zig-cache\o\762541bc2d17073d70cb6792c5fbd54b\cimport.zig:90966:293: note: pointer type child 'anyopaque' cannot cast into pointer type child 'fn (?*cimport.struct__LIBSSH2_SESSION, [*c][*c]u8, [*c]c_int, [*c]?*anyopaque) callconv(.C) void'
xxx\zig-cache\o\762541bc2d17073d70cb6792c5fbd54b\cimport.zig:57662:182: note: parameter type declared here
pub extern fn libssh2_userauth_password_ex(session: ?*LIBSSH2_SESSION, username: [*c]const u8, username_len: c_uint, password: [*c]const u8, password_len: c_uint, passwd_change_cb: ?*const fn (?*LIBSSH2_SESSION, [*c][*c]u8, [*c]c_int, [*c]?*anyopaque) callconv(.C) void) c_int;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src\main.zig:55:51: note: called from here
const aret = libssh2.libssh2_userauth_password(session, user, pass);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
referenced by:
callMain: ziglang.vscode-zig\zig_install\lib\std\start.zig:511:32
callMainWithArgs: ziglang.vscode-zig\zig_install\lib\std\start.zig:469:12
remaining reference traces hidden; use '-freference-trace' to see all reference traces
NULL -> ?*anyopaque, but anyopaque cannot -> fn pointer.
Maybe I'm wrong but I doubt this bug will help solve any problems. If you want to improve it, please show how to reproduce the error, preferably with the least amount of code and dependencies. Also, show what commands you ran.
A reproducible source code example, or a more detailed explanation, would be helpful.
It looks to me (and I might be wrong) like libssh2_userauth_password (originally translated from a macro) is called with third argument being *?anyopaque,
which then attempts to call libssh2_userauth_password_ex with the *?anyopaque given to its sixth argument.
As the error message states, *?anyopaque does not automatically coerce to a *const fn(...) ..., but I think using @ptrCast should do the trick.
Therefore if you wrap the argument given as passwd_change_cb, say x, as @ptrCast(x), it should work.
Since this seems to be coming from code generated by translate-c (via @cImport), it's a translate-c bug that the @ptrCast wasn't introduced automatically.
I was using libssh2 in my zig program,when i build with: zig build command,the error reported. this is the source code.
// zig main.zig
const libssh2 = @cImport(@cInclude("libssh2.h"));
....
const aret = libssh2.libssh2_userauth_password(session, user, pass);
the libssh2_userauth_password was a c macro.
// c libssh2.h
#define libssh2_userauth_password(session, username, password) \
libssh2_userauth_password_ex((session), (username), \
(unsigned int)strlen(username), \
(password), (unsigned int)strlen(password), \
NULL)
it translated to zig:
// zig cimport.zig
pub inline fn libssh2_userauth_password(session: anytype, username: anytype, password: anytype) @TypeOf(libssh2_userauth_password_ex(session, username, @import("std").zig.c_translation.cast(c_uint, strlen(username)), password, @import("std").zig.c_translation.cast(c_uint, strlen(password)), NULL)) {
_ = &session;
_ = &username;
_ = &password;
return libssh2_userauth_password_ex(session, username, @import("std").zig.c_translation.cast(c_uint, strlen(username)), password, @import("std").zig.c_translation.cast(c_uint, strlen(password)), NULL);
}
error reported at NULL,and the libssh2_userauth_password_ex in zig .
// zig cimport.zig
pub extern fn libssh2_userauth_password_ex(session: ?*LIBSSH2_SESSION, username: [*c]const u8, username_len: c_uint, password: [*c]const u8, password_len: c_uint, passwd_change_cb: ?*const fn (?*LIBSSH2_SESSION, [*c][*c]u8, [*c]c_int, [*c]?*anyopaque) callconv(.C) void) c_int;
the NULL not cast into the passwd_change_cb, it is a optional function pointer.
This seems to be a minimal reproduction
/tmp/tmp.h
void foo_ex(void (*foo_cb)(int)){
foo_cb(0);
}
#define NULL ((void*)0)
#define foo foo_ex(NULL)
/tmp/tmp.zig
const c = @cImport(@cInclude("/tmp/tmp.h"));
test "doesn't compile" {
_ = c.foo;
}
test "compiles" {
_ = c.foo_ex(@ptrCast(c.NULL));
}
$ zig test /tmp/tmp.zig
.../zig-cache/o/ee1809ebd18e6d2b9c2d15525fe76df2/cimport.zig:489:24: error: expected type '?*const fn (c_int) callconv(.C) void', found '?*anyopaque'
pub const foo = foo_ex(NULL);
^~~~
.../zig-cache/o/ee1809ebd18e6d2b9c2d15525fe76df2/cimport.zig:489:24: note: pointer type child 'anyopaque' cannot cast into pointer type child 'fn (c_int) callconv(.C) void'
.../zig-cache/o/ee1809ebd18e6d2b9c2d15525fe76df2/cimport.zig:57:34: note: parameter type declared here
pub export fn foo_ex(arg_foo_cb: ?*const fn (c_int) callconv(.C) void) void {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Duplicate of #5596