This example compiles and runs in Jupyter notebook and demonstrates the issue.
I'm having an issue this line,
memcpy(line.points, <point_t *> temp.data, sizeof(point_dtype) * n)
which I expect copies a buffer from numpy array temp to a points buffer in the C struct line.
I expect the value of points to be 1.0 but they are junk, basically uninitialised memory. What am I doing wrong!?
%%cython -a
import numpy as np
cimport numpy as cnp
from libc.stdlib cimport malloc
from libc.string cimport memcpy
cdef struct point:
cnp.float64_t x
cnp.float64_t y
ctypedef point point_t
cdef struct line:
point_t * points
ctypedef line line_t
point_dtype = np.dtype([
("x", np.float64),
("y", np.float64)
])
cdef line_t * make_line():
""" Make a line of 3 points. Internally does the creation using Numpy
and memcpy the result to the line_t C struct.
"""
# The number of points in the array
n = 3
cdef cnp.ndarray points = np.empty(n, dtype=point_dtype)
points["x"] = 0.0
points["y"] = 0.0
# Dynamically allocate a line C struct
line = <line_t*> malloc( sizeof(line_t) )
# Dynamically allocate space for "n" points
line.points = <point_t*> malloc( sizeof(point_t) * n)
# In this toy example we will modify "points" in a temporary array
# this is closer to what I'm trying to achieve in my actual code.
temp = np.empty(n, dtype=point_dtype)
temp[:] = points[:]
temp["x"] += 1.0
temp["y"] += 1.0
# Memory copy from the array's buffer into the struct
memcpy(line.points, <point_t *> temp.data, sizeof(point_dtype) * n)
print(line.points[0])
# {'x': 5e-324, 'y': 4.6451830626356e-310}
#
# !!!! Expected !!!!
# {'x': 1.0, 'y': 1.0}
# Assert fails
assert line.points[0].x == 1.0
assert line.points[0].y == 1.0
def test_create_line():
make_line()