Slimane amiar
Slimane amiar

Reputation: 1044

cython structure, string from python to cython

i would like to convert a python object to cython structure by doing as i did bellow, but it doesn't assigns the values of simres[1] to the resulta[x].cpt1

cdef struct resultaStructure:
    double score
    char **cpt1

simRes = [1.0,
['http://bioontology.org/projects/ontologies/fma/fmaOwlDlComponent_2_0#Abdomen', 
'Abdomen']]
cdef x = 0 
cdef resultaStructure *resulta = <resultaStructure *> malloc(sizeof(resultaStructure)*labelsSourceTaille)

resulta[x].score = simRes[0]
print("score : ",resulta[0].score)

resulta[x].cpt1 = <char**> malloc (sizeof (char**)*2)
print('2')
resulta[x].cpt1[0] = <char*> malloc (sizeof (char)*simRes[1][0].__len__()+1)
print('3')
resulta[x].cpt1[1] = <char*> malloc (sizeof (char)*simRes[1][1].__len__()+1)
print('4')
resulta[x].cpt1[0] = <char*> simRes[1][0]
print('5')
resulta[x].cpt1[1] = <char*>  simRes[1][1]
print('6')

print("cpt1 0 : ",resulta[0].cpt1[0])
print("cpt1 1 : ",resulta[0].cpt1[1])

here is the result

('score :', 1.0)

2

3

4

Upvotes: 4

Views: 928

Answers (2)

DavidW
DavidW

Reputation: 30888

The code in the question and in OP's answer has serious issues which will likely cause the program to crash in the long term.

1)

resulta[x].cpt1 = <char**> malloc (sizeof (char**)*2)

cpt1 is a pointer to (an array of) char pointers. Thus it should be assigned as

resulta[x].cpt1 = <char*> malloc (sizeof (char*)*2)

(Better yet, if the length is always 2 then assign char *cpt1[2] in the struct definition and you don't need to malloc it.)

This is unlikely to cause a real problem since all pointers are the same size but it's still wrong.

2) (The real problem part a)

resulta[x].cpt1[0] = <char*> malloc (sizeof (char)*simRes[1][0].__len__()+1)
# ...
resulta[x].cpt1[0] = <char*>some_python_string

Here you allocate some memory, the promptly forget about the memory you've allocated if favour of making the pointer point at a different area of memory owned by the Python string. What you don't do is copy data from the Python string into your allocated memory.

3) (The real problem part b)

str1 = simRes[1][0].encode('UTF-8')
resulta[x].cpt1[0] = <char*> str1

The memory that cpt1[0] points to is owned by str1. If str1 gets freed before you've finished using your structure then the structure points to invalid memory and your program will crash, or read some random data that's allocated later, or some other bad thing.

If you can guarantee that str1 will outlive your structure (for example, your structure is used as an argument for one C function call) then this is OK, but in the general case it probably isn't.

The solution is to copy the contents or str1 into your newly allocated memory:

resulta[x].cpt1[0] = <char*> malloc (sizeof (char)*len(simRes[1][0])+1)
strcpy(resulta[x].cpt1[0],str1)

(Also, You are remembering to free all the memory you've malloced, right?)

Upvotes: 2

Slimane amiar
Slimane amiar

Reputation: 1044

the solution is by encoding the python string before assignment as follow ,

str1 = simRes[1][0].encode('UTF-8')
resulta[x].cpt1[0] = <char*> str1
print('5')
str2 = simRes[1][1].encode('UTF-8')
resulta[x].cpt1[1] = <char*> str2

Upvotes: 1

Related Questions