Python SWIG arrays - python

I am wrapping a C module with SWIG for Python. Is there any way to turn all Python lists/tuples whose members are all of the same type (same kind of Swig object) to C arrays?

Typemaps. What you are most likely looking for is an "in" typemap, which maps Python types to C types. The declaration looks something like this:
%typemap(in) {
/* C code to convert Python tuple object to C array */
}
Inside the typemap code you can use the variable $input to reference the PyObject* to convert, and assign your converted C array to $1.
http://docs.python.org/c-api/ has information on the Python/C API, which you'll need to unpack the tuple to get the items and convert them to C.
http://www.swig.org/Doc1.3/Typemaps.html has the SWIG documentation for typemaps.
The documentation can be hard to understand at first, so take a look at some example typemaps in /share. carrays.i in that directory might also serve as a good starting point.

Related

Convert python dict to a structure using ctypes

I have a structure like this:
struct Person {
std::string name;
int age;
std::string title;
float income;
};
In the python side, I have a dict like this:
person = { 'name':'Alex',
'age':36,
'title':'programmer',
'income':13435.40
}
Now I want to convert the Python dict to the C++ program by using ctypes. There is a stupid way to do this task is that we can write 4 c-style functions to set these four elements independently. How can we do this task in a single function, which can solve different data type (string, int, float)?
ctypes can't handle C++ on its own.
SWIG can though this is equivalent to writing a C wrapper for the C++ code. It requires building native code.

Using SWIG typemaps to generate overloaded Python wrapper

I am using SWIG to generate Python bindings for a library (lets call it Spam) that is written in C++. The library internally defines its own Vector datatype, defined in the Spam::Vector class.
Consider the following functions to be wrapped:
void ham(Spam::Vector &vec_in, Spam::Vector &vec_out);
void eggs(Spam::Vector &vec_in, double arg2, double result);
I would like to be able to call these functions using Python lists AND NumPy arrays as inputs (instead of having to create a Spam::Vector object in Python and then populate it using the associated C++ methods - it is very unpythonic).
How would I go about writing the SWIG typemap to achieve this? Also, is there a way to incorporate/leverage numpy.i for this purpose?
The right way to do this is with a custom typemap. Precisely what this will look like depends a lot on the type Spam::Vector itself. In general though you can do this with something like:
%typemap(in) {
// Maybe you'd rather check for iterable here, with this check after numpy?
if (PyList_Check($input)) {
$1 = ... // Code to iterate over a list and prepare a Spam::Vector
}
else if (PyType_IsSubtype($input->ob_type, NumpyType)) {
$1 = ... // Code to convert from numpy input
}
else {
// code to raise an error
}
}
There are various hacks that might be possible in other more specific circumstances, but this is the general solution.

How does python have different data types in an array?

Python can have a list with different data types in it i.e. [1,"two",3]. Python was implemented in c, so how would I create an array with different data types in it using c?
So, I have no idea how it is implemented in Python, but in C there are ways to operate on generic data. in its most simple form:
void *array[size];
Now you have an array full of void*. Each void* can point to anything. You would want some extra information as well to tell you the size of the thing it points to.
typedef struct {
void *data;
size_t size;
} elem;
You could represent the actual type if needed via a variety of methods. You can use unions to hold one of N types in the same variable. Anyway, the point is that there are various ways to do operate on generic data in C.
What if your array consisted of C structs of the form:
struct slot {
int type;
char *data;
};
Now you have an array that can contain arbitrary types of data, as long as you can represent them as pointers-to-char.
This isn't, of course, how Python does it; the point is that there doesn't have to be any connection between how your application handles data and how your implementation language handles data.
how would I create an array with different data types in it using c?
You can't; C is a statically-typed language.
You can, however, use things like unions:
typedef union {
int i;
float f;
} Foo;
Foo array[3];
array[0].i = 3;
array[1].f = 4.2;
...
You can also use void * to point at any objects you like, but this requires careful memory management.
In Python, there are no “raw” values; everything is an object and knows its type. Even integers are objects (try printing (1).__class__ or 1 .__class__). Everything you do in C with Python objects, you do through a PyObject * (a pointer to the object).¹
A Python list is a dynamic (i.e. resizable) array of PyObject *. Since every object knows its type, the list doesn't have to be declared as having members of a specific type.
¹ Also note: Python does not have “variables” in the usual sense (C, BASIC, Pascal etc), where a typed variable contains a value; it has namespaces and names (actually, dictionaries mapping strings to objects; a namespace is a dictionary, its keys are the names, its values are the pointers to the objects pointed to by each name).

How to define a C struct which contain a struct inside a Ctype python

Hi
I am learning python and using ctype to embedd 'C' in python. My query is-
How to use C stru which again calling a stru inside into cytpe/python.
typedef struct {
struct *i, *j;
BOOLEAN z;
} foo;
It's not entirely clear from your question, but it looks like you're trying to define a struct that contains a pointer to the same type. It's not immediately obvious how you would accomplish this in python, but you basically define your Structure, and then define the _fields_ attribute afterwards.
The ctype docs on python.org have a perfectly on-point example of doing exactly this.
There's also good documentation there on working with structs in general, including nesting one struct type within another, which works a little more obviously.

Creating Instance of Python Extension Type in C

I am writing a simple Vector implementation as a Python extension module in C that looks mostly like this:
typedef struct {
PyObject_HEAD
double x;
double y;
} Vector;
static PyTypeObject Vector_Type = {
...
};
It is very simple to create instances of Vector while calling from Python, but I need to create a Vector instance in the same extension module. I looked in the documentation but I couldn't find a clear answer. What's the best way to do this?
Simplest is to call the type object you've created, e.g. with PyObject_CallFunction -- don't let the name fool you, it lets you call any callable, not just a function.
If you don't have a reference to your type object conveniently available as a static global to your C module, you can retrieve it in various ways, of course (e.g., from your module object with a PyObject_GetAttrString). But sticking that PyObject* into a static module-level C variable is probably simplest and most convenient.

Categories