Note that Foo is not extern. This is by design. So I can’t return it to python. I just return a pointer to it and expect the pointer to be passed in order to do things with the structure on zig side.
I compile with:
zig build-lib python.zig -dynamic
In python I do:
import ctypes
lib = ctypes.CDLL("./libpython.so")
f = lib.foo()
print(f'0x{f:02X}')
lib.bar(f)
And I get a crash on the last line of bar. Note that my pointers looks correct:
Variable f is a function local variable. When foo function terminates, f lifetime also ends. By returning the address of f you actually return an address to a temporary storage that is reused when f returns.
So bar get this address, that points to something random; then it tries to dereference the random contents, it crashes.
Looking at the pointer values, it seems that the pointer get sliced to 32bits when going through python.
Looking on google, it seems many people are struggling passing pointers back and forth with ctypes. So I think this is a ctypes issue and not a zig issue.
So in addition to the aforementioned local variable issue, there was a ctypes problem, so posting it here for posterity:
import ctypes
lib = ctypes.CDLL("./libpython.so")
# You need to add this following line or your pointer will be truncated
lib.foo.restype = ctypes.c_void_p
f = lib.foo()
print(f'0x{f:02X}')
# You need to add this following line or your pointer will be truncated
lib.bar.argtypes = (ctypes.c_void_p,)
lib.bar(f)
You need to use restype and argtypes to specify that your function deal with pointers. By default, ctypes will consider everything a i32.