ctypes.cast.
>>> import ctypes
>>> c_long_p = ctypes.POINTER(ctypes.c_long)
>>> some_long = ctypes.c_long(42)
>>> ctypes.addressof(some_long)
4300833936
>>> ctypes.cast(4300833936, c_long_p)
<__main__.LP_c_long object at 0x1005983b0>
>>> ctypes.cast(4300833936, c_long_p).contents
c_long(42)
Answer from habnabit on Stack Overflow[FEAT] being able to enforce the dereferencing of the smart pointer in argument conversion
Why is there no concept of a pointer or pass-by reference in python? Is there something I can use
I am a C++ and assembly developer mainly, but as someone entering the job market that just doesn't cut it. I have a job I got hired for where I'm taking 4+ years of a python codebase that no one has documented and is spaghetti and updating it, and was supposed to be adding multithreading (EXCEPT THERE IS NO TRUE MULTITHREADING SO I HAVE TO DO MULTIPROCESSING WHICH IS A CLUSTER-F***). So that blows.
BUT
why is there no pointers!? or way to go references? I need to store data in an object that gets passed into some libraries, and then the library runs callbacks where I analyze the crap. From there I need to set the values so in other callbacks I can work with the values. It's a dictionary so I can add some new keys to store the data... except I can't because it's like pass by value so the data instantly gets deleted once it returns from the callback. If I passed in a pointer I'd be set, except that's not possible...
That's just one issue in a mirad of issues I'm facing with this junk language. Not to even mention the horribleness of everything using like 2gb of memory because each process copies the entire memory space of the head process....
Please tell me there's some kinda object or pointer thing I can use.
EDIT : I got the help I needed here, thanks everyone! sorry to trash the language a bit above I was just frustrated lol
I can't test this right now, but this is what I would try:
import numpy as np
result = ...
shape = (10, 2)
array_size = np.prod(shape)
mem_size = 8 * array_size
array_str = ctypes.string_at(result, mem_size)
array = np.frombuffer(array_str, float, array_size).reshape(shape)
array will be read only, copy it if you need a writable array.
Here is a solution that uses ctypes.cast or numpy.ctypeslib.as_array, and no ctypes.string_at just in case if it makes an extra copy of memory region.
class _FFIArray(Structure):
_fields_ = [("data", c_void_p), ("len", c_size_t)]
class Coordinate(Structure):
_fields_ = [("latitude", c_double), ("longitude", c_double)]
class Coordinates(Structure):
_fields_ = [("data", POINTER(Coordinate)), ("len", c_size_t)]
decode_polyline = lib.decode_polyline_ffi
decode_polyline.argtypes = (c_char_p, c_uint32)
decode_polyline.restype = _FFIArray
# assuming that the second argument is the length of polyline,
# although it should not be needed for `\0` terminated string
res = decode_polyline(polyline, len(polyline))
nres = Coordinates(cast(res.data, POINTER(Coordinate)), res.len)
for i in range(nres.len):
print(nres.data[i].latitude, nres.data[i].longitude)
# if just a numpy (np) array is needed
xs = np.ctypeslib.as_array((c_double * res.len * 2).from_address(res.data))
# "New view of array with the same data."
xs = xs.view(dtype=[('a', np.float64), ('b', np.float64)], type=np.ndarray)
xs.shape = res.len