luvjoey
luvjoey

Reputation: 23

pure-python callback function was called with parameter b'', lossing the actual data in cython function

I try to call a callback function in cython cdef block, I can printf the actual data during cython function call, but when my callback function was called or I call a print(buffer) in cython cdef block, I got the (paramter/result) with b'',I try other demo, It's all works fine.

windows 10, python3.7, cython

cython block
    cdef ikcp_output(self, char *buffer, int size):
        print("size: {}".format(size)) this can work
        for i in range(size):
            print(buffer[i]) # this can also works
        cdef char* o
        o = <char*> malloc(sizeof(char) * size)
        memcpy(o, buffer, size)
        for i in range(size): 
            print(o[i]) # this can also works
        print(o) # this output b''
        self.output(o) # the callback function get a parameter b''
        free(o)
start iter buffer
0
0
0
1
81
0
0
32
28
-50
-113
-50
0
0
0
0
0
0
0
0
49
50
49
51
50
49
51
49
51
49
50
10
start iter o
0
0
0
1
81
0
0
32
28
-50
-113
-50
0
0
0
0
0
0
0
0
49
50
49
51
50
49
51
49
51
49
50
10
32
b'' # this is what i got in callback function
client output
output data b'' to addr: ('127.0.0.1', 8888)

Upvotes: 0

Views: 47

Answers (1)

DavidW
DavidW

Reputation: 30887

Calling either print(o) or self.func(o) involves converting o to a Python object, in this case a bytes object. This conversion assumes that the char* is a c string (i.e. is null terminated) since Cython has no other way to determine the length. However your buffer starts with 0, and so is read a 0-length string.

The correct solution is to do the conversion manually using PyBytes_FromStringAndSize. You pass this a char* and the length of the string (hence it doesn't assume that the first 0 is the end of the string). You can cimport it from cpython.bytes.

Upvotes: 1

Related Questions