I'm trying to use a C struct in Cython, that defines a linked list:
typedef struct {
struct query_result* next_result;
char* result;
} query_result;
As you can see I'm using the query_result type inside its own definition.
Using this as is, in Cython gives me compiler errors:
cdef extern from 'c_wrapper.h':
struct query_result:
struct query_result*
char*
Any ideas about how to properly handle this recursive definition in Cython?
You shouldn't use the struct keyword when you are referring to the type:
cdef extern from 'c_wrapper.h':
struct query_result:
query_result* more
char* data
Related
I have a pxd file that declares some types with ctypedef, and some functions with cdef. To call one particular function, I have to duplicate the typedefs in my pyx file.
If I move the cdef of the function into the pyx file it fails to compile with "Cannot convert 'state_t *' to Python object". The error refers to this line of code
retval = c_explanation.table_of_states_is_bad(<state_t*>test_array, b)
The test_array parameter is created locally with malloc so is not a python object at all.
If remove the typedefs from the pyx file and import them and the cdef from the pxd file with a from .. import *, I get the same compile error.
The only way that I can get this simple bit of code to work is with the rather awkward duplication of typedefs in both pyx and pxd files.
Any thoughts on what is going on here and how to resolve it?
The full code is pasted below
pyx file
from libc.stdlib cimport malloc, free
cimport c_explanation
cdef extern from "explanation.h":
ctypedef int state_id;
ctypedef struct event_t:
pass
ctypedef void (*event_handler)(event_t event)
ctypedef struct state_t:
state_id id
event_handler handle
char *name
ctypedef enum bool:
pass
def table_of_states_is_bad(a, b):
cdef state_t *test_array
cdef bool retval
test_array = <state_t*>malloc(len(a) * sizeof(state_t))
if not test_array:
raise MemoryError()
try:
for i, s in enumerate(a):
test_array[i].id = s[0]
retval = c_explanation.table_of_states_is_bad(test_array, b)
return retval
finally:
free(test_array)
pxd file
cdef extern from "explanation.h":
cdef int mock_get_temp(int)
ctypedef enum bool:
pass
ctypedef struct event_t:
pass
ctypedef void (*event_handler)(event_t event);
ctypedef int state_id;
ctypedef struct state_t:
state_id id
event_handler handle
char *name
cdef bool table_of_states_is_bad(state_t table[], size_t size)
finally the h file
int mock_get_temp(int);
typedef int event_id;
/* an event */
typedef struct {
event_id id; /* numeric id */
void *data; /* points to anything */
char *name; /* points to string for debug or log */
} event_t;
typedef void (*event_handler)(event_t event);
typedef enum { false, true } bool;
typedef int state_id;
/* a state */
typedef struct {
state_id id; /* numeric id */
event_handler handle; /* points to handler */
char *name; /* points to string for debug or log */
} state_t;
bool table_of_states_is_bad(state_t table[], size_t size);
After some reading and experimentation I worked out what I had done wrong.
The problem is one of namespaces. When using the import * format, the local definition of table_of_states_is_bad() was replacing the imported one. Thus the function call was to the cython version of the function rather than to the c version and hence the error was correctly reported.
I solved the problem by renaming the local function to wrap_table_of_states_is_bad() hence resolving the name conflict.
So, if you've got a header file.
%%file test.h
struct mystruct{
int i;
int j;
};
And then you wrap it in Cython:
cdef extern from "test.h" nogil:
struct mystruct:
int i
int j
And some function that returns back out to Py:
def spit_out_dict():
return mystruct(5,10)
Cython correctly automatically generates a dict wrapper. However, when I wrap the original C header in a namespace, I haven't been able to get get Cython to still generate the dict wrapper correctly, something along these lines:
%%file test2.h
namespace outerspace{
struct mystruct{
int i;
int j;
};
}
And Cython/Python:
cdef extern from "test2.h" namespace "outerspace" nogil:
struct mynewstruct:
int i
int j
def spit_out_dict():
return mynewstruct(5,10)
This won't compile -- lots of namespace complaint errors -- anyone experienced this before?
Your problem is that Cython seems to only expect namespaces to be used with cppclass. For structs, it generates some functions but just copies the full namespaced name in, causing errors:
static PyObject* __pyx_convert__to_py_outerspace::mystruct(struct outerspace::mystruct s);
^
py_bit.cpp: In function ‘PyObject* __pyx_pf_6py_bit_spit_out_dict(PyObject*)’:
py_bit.cpp:721:15: error: ‘__pyx_convert__to_py_outerspace’ has not been declared
where it's trying to create a function called __pyx_convert__to_py_<classname>. (I think this might be worth submitting a bug report for.)
The trick in such circumstances is usually to lie to Cython. I create three files:
// test2.hpp
namespace outerspace{
struct mystruct{
int i;
int j;
};
}
,
// test2_cy.hpp - a wrapper file purely for Cython's benefit
#include "test2.hpp"
using outerpsace::mystruct;
and the cython file
cdef extern from "test2_cy.hpp": # (I didn't test with "nogil", but it's probably fine...)
struct mynewstruct:
int i
int j
def spit_out_dict():
# for some reason using "return mystruct(5,10)" doesn't work, but this does...
cdef mystruct a = mystruct(5,10)
return a
This is a bug in Cython, fixed at https://github.com/cython/cython/commit/fa946e8435a4dcc3497fc7b0f4e87256d40844ba
In Storing C++ template function definitions in a .CPP file one can learn how to store a template implementation in .cpp. However I failed to do it if the return type is a struct which is defined inside the class. See,
template<typename T>
class C1
{
public:
struct s {
int x;
};
s GetS();
private:
s m_sInt;
};
in its .cpp, the below code will generate syntax errors.
template<typename T>
C1<T>::s C1<T>::GetS()
{
return m_sInt;
}
Wonder what the right syntax should be in this case.
template<typename T>
typename C1<T>::s C1<T>::GetS()
{
return m_sInt;
}
The behaviour of compiler is explained in other questions about nested templates with dependent scope, e.g. Nested templates with dependent scope or Dependent scope and nested templates
A usual way to target different floating point precisions (float / double) is either by typedefs
typedef float Real;
//typedef double Real;
or by using templates
template<typename Real>
...
This is convenient, but anyone has ideas how to use the CUDA types float2/float3/... and make_float2/make_float3/... ? Sure, I could make #defines or typedefs for all of them but that seems not very elegant.
You can implement helper class that will concatenate type and channels number:
template <typename T, int cn> struct MakeVec;
template <> struct MakeVec<float, 3>
{
typedef float3 type;
};
template <> struct MakeVec<double, 3>
{
typedef double3 type;
};
// and so on for all combination of T and cn
Usage:
template <typename T>
void func()
{
typedef typename MakeVec<T, 4>::type vec4_type;
vec4_type vec4; // for T=float it will be float4, for T=double it will be double4
}
You can find implementation here
Amazingly I can't seem to find a single example of getting elements of a struct, by name (both on the web and in the cython examples).
So I'm receiving a pointer to a struct out of a C function, and would want to access those elements one by one and repackage them into a python list/dict.
maybe:
structPointer['propertyName']
or
structPointer.propertyName
I want to get the effect of structName->propertyName.
Your second syntax is the correct one, but you have to have an extern declaration for the struct type:
cdef extern from "someheader.h":
struct properties_t:
int value1
int value2
properties_t* getthem()
cdef void foo():
cdef properties_t* prop
prop = getthem()
i = prop.value1