In an attempt to speed up struct.pack()
, I have the following to pack an int to bytes:
import cython as c
from cython import nogil, compile, returns, locals, cfunc, pointer, address
int_bytes_buffer = c.declare(c.char[400], [0] * 400)
@locals(i = c.int, num = c.int)
@returns(c.int)
@cfunc
@nogil
@compile
def int_to_bytes(num):
i = 0
while num >0:
int_bytes_buffer[i] = num%256
num//=256
i+=1
return int_bytes_buffer[0]
int_to_bytes(259)
I'm trying to get this to work on a list of ints, with the following bad code:
@locals(i = c.int, ints_p = pointer(c.int[100]), num = c.int)
@returns(c.int)
@cfunc
@nogil
@compile
def int_to_bytes(num):
i = 0
for num in ints_p:
while num >0:
int_bytes_buffer[i] = num%256
num//=256
i+=1
return int_bytes_buffer[0]
ints = c.declare(c.int[100], [259]*100)
int_to_bytes(address(ints))
which gives me:
for num in ints_p:
^
----------------------------------------------------------
Accessing Python global or builtin not allowed without gil
Evidently I shouldn't be using in
, or looping over a pointer.
How can I loop over the list-made-array inside the function?
EDIT:
I'm trying to pass a pointer to an array of ints to the function, and have it work without the gil so it can be parallelized.
The parameter to the function should've been ints_p:
@locals(ints_p = pointer(c.int[100]), i = c.int, num = c.int)
@returns(c.int)
@cfunc
@nogil
@compile
def int_to_bytes(ints_p):
i = 0
for num in (*ints_p):
while num >0:
int_bytes_buffer[i] = num%256
num//=256
i+=1
return int_bytes_buffer[0]
ints = c.declare(c.int[100], [259]*100)
int_to_bytes(address(ints))
and I want to run over the actual ints and pack them (without the gil)
EDIT 2:
I am aware of struct.pack
. I wish to make a parallelizeable variant with cython and nogil
.