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
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.
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.
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).
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.
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.