How to declare linked lists with pointers in Cython - python

I am trying to create a linked list in Cython for the following C code:
typedef struct my_struct *my_val;
typedef struct my_struct {
int i;
my_val next_val;
}
This didn't work:
cdef my_struct* my_val
cdef struct bc_struct:
int i
my_val next_val
I get this error on the first cdef:
'my_val' is not a type identifier
Neither did this:
cdef struct my_struct* my_val
This gives an error on the first cdef:
Syntax error in struct or union definition
Any help is much appreciated!

From what i have read so far cdef is not the equivalent of a typedef. Instead you are declaring C variables. Try using ctypedef instead as descriped in the link.
EDIT: A bit more explanation.
When you use cdef mystruct* my_val you are not performing a typedef, instead you are declaring the C variable my_val which is of type mystruct *. When you now try to use it as a type specifier like in your class, it of course tells you that it is not a specifier since it is a variable. If you use ctypedef instead it performs a typedef
ctypedef mystruct *my_val
for the second cdef struct mystruct* my_val it throws a syntax error because the syntax is cdef type name and thus you try to initialize a variable called mystruct* of type struct and have also a trailing my_val expression behind it.

Related

Wrapping a C function in Cython which has non-stanard types as arguments

I am trying to wrap a C++ function that has arguments of type uint32_t, which can be found in the cstdint library. Let's say the C++ file looks like
cppfile.cpp:
#include <cstdint>
int foo(uint32_t x){
return 1;
}
How do I wrap this in a Cython .pxd file? If x was just a normal integer, I would do
cdef extern from "cppfile.cpp":
cdef int foo(int x)
But how do I do this when x is of type uint32_t? How do I obtain the uint32_t as a type in cython?
This is a question answered in the FAQ of cython
from libc.stdint cimport uint32_t
cdef extern from "cppfile.cpp":
cdef int foo(uint32_t x)

How to use #define as size of char array in Cython

c++ header (some.h) contains:
#define NAME_SIZE 42
struct s_X{
char name[NAME_SIZE + 1]
} X;
I want to use X structure in Python. How could I make it?
I write:
cdef extern from "some.h":
cdef int NAME_SIZE # 42
ctypedef struct X:
char name[NAME_SIZE + 1]
And got an error: Not allowed in a constant expression
It often doesn't really matter what you tell Cython when declaring types - it uses the information for checking you aren't doing anything obviously wrong with type casting and that's it. The cdef extern "some.h" statement ensures that some.h is included into to c-file Cython creates and ultimately that determines what is complied.
Therefore, in this particular case, you can just insert an arbitary number and it will work fine
cdef extern "some.h":
cdef int NAME_SIZE # 42
ctypedef struct X:
char name[2] # you can pick a number at random here
In situations it won't work though, especially where Cython has to actually use the number in the C code it generates. For example:
def some_function():
cdef char_array[NAME_SIZE+1] # won't work! Cython needs to know NAME_SIZE to generate the C code...
# other code follows
(I don't currently have a suggestion as to what to do in this case)
NAME_SIZE doesn't actually exist in your program so you'll probably have to hardcode it in the Python.
Despite how it looks in your C source code, you hardcoded it in the C array declaration, too.

How to wrap C file with extern variables with Cython

I want to wrap a quite long C function published by a scientist with Cython. I am following
http://scipy-lectures.github.io/advanced/interfacing_with_c/interfacing_with_c.html#interfacing-with-c
and I am able to replicate the examples with numpy support.
I am confused about what to do (or to do anything at all) about variables declared as extern in the library.cpp. Obviously, I will have a main.py that will call this function, not a main.cpp. How should I declare ini_flag and A and pass to func? Is there any other way than making them arguments to the function? If possible I would prefer not to edit original library.cpp file.
// main.cpp:
int ini_flag=0, *A;
void main(){
func(...)
...
}
// library.cpp:
extern int ini_flag, *A;
void func(...){
if (ini_flag==0){
// malloc and initialize A
ini_flag=1;
}
// use A and do other stuff
}
You should create a corresponding library.hpp file:
int ini_flag, *A;
void func(...)
And then in Cython:
cdef extern from "library.hpp":
int ini_flag, *A
void func(...)
Then you can then use them normally in Cython.

Accessing C struct array to Python with SWIG

I attempting to call into existing C code from Python. The C code defines a struct B that contains an struct array of As. The C code also defines a function that puts values into the structure when called. I can access the array member variable, but it is not an list (or something that supports indexing). Instead, I am getting an object that is a proxy for B*.
I found this question, but it doesn't look like it was completely resolved. I'm also not sure how to make an instance of the Python class B to replace the PyString_FromString().
Below is the code needed to demonstrate my issue and how to execute it:
example.h
typedef struct A_s
{
unsigned int thing;
unsigned int other;
} A_t;
typedef struct B_s
{
unsigned int size;
A_t items[16];
} B_t;
unsigned int foo(B_t* b);
example.c
#include "example.h"
unsigned int
foo(B_t* b)
{
b->size = 1;
b->items[0].thing = 1;
b->items[0].other = 2;
}
example.i
%module example
%{
#define SWIG_FILE_WITH_INIT
#include "example.h"
%}
%include "example.h"
setup.py
from distutils.core import setup, Extension
module1 = Extension('example', sources=['example.c', 'example.i'])
setup(name='Example', version='0.1', ext_modules=[module1])
script.py - This uses library and demonstrates the failure.
import example
b = example.B_t()
example.foo(b)
print b.size
print b.items
for i in xrange(b.size):
print b.items[i]
How to run everything:
python setup.py build_ext --inplace
mv example.so _example.so
python script.py
you could write some C helper functions like:
int get_thing(B_t *this_b_t, int idx);
int get_other(B_t *this_b_t, int idx);
void set_thing(B_t *this_b_t, int idx, int val);
void set_other(B_t *this_b_t, int idx, int val);
wrap these and you can then use the pointer that you get from example.B_t() to access values from within your data-structure arrangement, e.g.
>>> b = example.B_t()
>>> a_thing = example.get_thing(b, 0)
>>> example.set_thing(b,0,999)
Hopefully its obvious what the implementation of these C functions should be - if not I could provide an example...
granted this isn't as seamless as being able to access C arrays as python lists - you might be able to use typemaps to achieve this but I can't remember the exact syntax you would need in this instance - you'd have to do a bit of RTFM on the SWIG documentation
also possible duplicate here: nested structure array access in python using SWIG

Cython: Nesting a union within a struct

In Cython glue declarations, how do I represent a C struct type containing an anonymous union? For example, if I have a C header file mystruct.h containing
struct mystruct
{
union {
double da;
uint64_t ia;
};
};
then, in the corresponding .pyd file
cdef extern from "mystruct.h":
struct mystruct:
# what goes here???
I tried this:
cdef extern from "mystruct.h":
struct mystruct:
union {double da; uint64_t ia;};
but that only gave me "Syntax error in C variable declaration" on the union line.
For those who got here via Google, I found a solution to this. If you have a struct:
typedef struct {
union {
int a;
struct {
int b;
int c;
};
}
} outer;
You can flatten it all out in the Cython declaration, like so:
ctypedef struct outer:
int a
int b
int c
Cython isn't generating any code that makes any suppositions about the memory layout of your struct; you're only telling it the de facto structure of what you're calling by telling it what syntax to generate to call it. So if your structure has a member of size int that can be accessed as ((outer) x).a, then you can throw a on the struct definition and it will work. It's operating on textual substitution, not memory layout, so it doesn't care about whether these things are in anonymous unions or structs or what have you.
You can't nest declarations to the best of my knowledge, and Cython doesn't support anonymous unions AFAIK.
Try the following:
cdef union mystruct_union:
double lower_d
uint64_t lower
cdef struct mystruct:
mystruct_union un
Now access the union members as un.lower_d and un.lower.

Categories