python extending and embedding · bodenseo Extending and Embedding SWIG S implified Wrapper and I nterface G enerator Swig wandelt vollautomatisch C/C++ Code in Skripting-Sprachen.
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Grundsätzlich gibt es zwei Vorgehensweisen, ein Programm zu schreiben, das Python mit einer anderen Sprache kombiniert:● In einem Python-Programm soll eine andere Sprache (z.B. C)
ausgeführt werden.● In einem Programm in einer anderen Sprache (z.B. C) soll ein
Dynamisch ladbare Bibliotheken können mit dem Modul ctypes in Python eingebunden werden, also z.B. DLL-Dateien (Dynamic Link Library) unter Windows oder SO-Dateien (Shared Object) unter Linux/Unix.
Eine dynamische Bibliothek ist nicht notwendigerweise aus einem C oder C++ Programm erstellt worden.
Dynamische Bibliotheken sind sprachunabhängige Schnittstellen zwischen verschiedenen Programmen. Voraussetzung ist nur, dass es sich um eine kompilierbare Sprache handelt.
Einbinden einer eigenen Libraryint fak(int n) { int i; int fac; for (i = 1, fac = 1; i <= n; i++) fac *= i; return fac; }
int komb(int k, int n) {/* Anzahl: k Objekte werden aus n Objekten ohne Berücksichtigung der Reihenfolge ausgewählt*/ int anzahl; anzahl = fak(n) / (fak(k) * fak(n - k)); return anzahl;}
parses the parameters of a function that takes only positional parameters into local variables. Returns true on success; on failure, it returns false and raises the appropriate exception.
The args argument must be a tuple object containing an argument list passed from Python to a C function. "i:fact" is the format stringThe following arguments are addresses of variables whose type is determined by the format string, in our case only &n
The format string "i:fact" defines that n must be an integer (the i in front of the colon) defines the error message, which will be used instead of the default error message.
int ok;int i, j;char *s;int size;char *file;char *mode = "r";int bufsize = 0;
A pair of ints and a string, whose size is also returned:ok = PyArg_ParseTuple(args,"(ii)s#", &i, &j, &s, &size); /* Possible Python call: f((1, 2), 'three') */
A string, and optionally another string and an integer: ok = PyArg_ParseTuple(args, "s|si", &file, &mode, &bufsize); /* Possible Python calls: f('spam') f('spam', 'w') f('spam', 'wb', 100000) */
Create a new value based on a format string and a sequence of values. Returns the value or NULL in the case of an error; an exception will be raised if NULL is returned.
Py_BuildValue does not always build a tuple. It builds a tuple only if its format string contains two or more format units. If the format string is empty, it returns None; if it contains exactly one format unit, it returns whatever object is described by that format unit. To force it to return a tuple of size 0 or one, parenthesize the format string.
Solution:All we have to do is change the last line of the wrap_fact() function from return Py_BuildValue("i", n, result);intoreturn Py_BuildValue("(n, i)", n, result);
/* example.i */%module example%{/* header files here or function declarations like below: */extern double My_variable;extern int fact(int n);extern int my_mod(int x, int y);extern char *get_time();%}
extern double My_variable;extern int fact(int n);extern int my_mod(int x, int y);extern char *get_time();
Constants and enum in CDeclarations with #defineconst enumare turned into Python variables:
see example constants_enums
%module ultimate%{#define VERSION "1.0"
enum days {Mon,Tue,Wed,Thu,Fri,Sat,Sun};%}#define VERSION "1.0"enum days {Mon,Tue,Wed,Thu,Fri,Sat,Sun};%constant int SPECIAL = 42;%constant const char *question = "The Ultimate ...";
Using the „ultimate“ ModuleHelp on module ultimate:
NAME ultimate
DESCRIPTION # This file was automatically generated by SWIG (http://www.swig.org). # Version 2.0.11 # # Do not make changes to this file unless you know what you are doing--modify # the SWIG interface file instead.
DATA Fri = 4 Mon = 0 SPECIAL = 42 Sat = 5 Sun = 6 Thu = 3 Tue = 1 VERSION = '1.0' Wed = 2 question = 'The Ultimate Question is the actual question behind the Ul...
Using the module in Python3:>>> import boxes>>> x = boxes.newBox(3,2,5)>>> type(x)<class 'boxes.Box'>>>> x.height5.0>>> x.height = 7>>> x.height7.0>>> y = boxes.Box()>>> y.length0.0
Structures involving character strings can also be defined. They will be dynamically allocated using malloc() and they are NULL-terminated ASCII strings. When such a member is modified, the previously contents will be released, and the new contents allocated.
Using the „example“ module>>> import example>>> example.fact(10)Received an integer : 103628800>>>
In the previous example, the typemap is applied to all occurrences of the „long“ datatype. We can refine this by supplying an optional parameter name. For example:
%typemap(in) long n {$1 = (long) PyLong_AsLong($input);
if ($1 <= 0) PyErr_SetString(PyExc_ValueError,"Expected a positive value."); return NULL; }}
The typemap code will only be applied to arguments which exactly match „long n“ (not „long m“ e.g.)
void add(double a, double b, double *result) { *result = a + b;}
A human reader understands, that this function is storing a „return“ value in the double *result parameter. However, SWIG has no way to know that this is the underlying behavior. One way to deal with this problem is to use the typemaps.i library.
The typemap stays in effect for all other occurrences of the type and name. For example, we can define further similar functions for our previous example:
%module functions%include "typemaps.i"
%apply double *OUTPUT { double *result };
%inline %{extern void add(double a, double b, double *result);extern void sub(double a, double b, double *result);extern void mul(double a, double b, double *result);%}
%typemap(out) double *bar %{ $result = PyList_New(2); // size of list for (int i = 0; i < 2; ++i) { PyList_SetItem($result, i, PyFloat_FromDouble($1[i])); } delete $1; // important to avoid a memory leak%}
public: Clock( int h, int min, int sec); void set( int h, int min, int sec); int getHours() { return hours; }; int getMinutes() { return minutes; }; int getSeconds() { return seconds; };
Ruft man das kompilierte Programm auf, erhält man:$ ./a.outembed-simplePython 2.6.4 (r264:75706, Nov 2 2009, 14:54:49) [GCC 4.4.1] on linux2Type "help", "copyright", "credits" or "license" for more information.>>>