Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
17-0: Using C code from Python Sometimes, you might want to call C/C++ code from Python. Programming Language Paradigms What are some examples? Extending Python with C Chris Brooks Department of Computer Science University of San Francisco Department of Computer Science — University of San Francisco – p.2/?? Department of Computer Science — University of San Francisco – p.1/?? 17-1: Using C code from Python Sometimes, you might want to call C/C++ code from Python. 17-2: Using C code from Python Optimize performance There are two approaches to combining C ond Python Write wrapper code by hand. Use an automatic wrapper generator Interface with a third-party package We’ll take a brief look at each. Integrate legacy code into a new application. Department of Computer Science — University of San Francisco – p.3/?? 17-3: Hello World Let’s start with Hello World. No inputs or outputs, just a function to be called: Department of Computer Science — University of San Francisco – p.4/?? 17-4: Hello World We need to create a Python object representing this function: PyObject *wrap_HelloWorld(PyObject *self, PyObject *args) { HelloWorld(); return Py_BuildValue(""); } /* function to be wrapped */ void HelloWorld () { printf("Hello World\n"); Py_BuildValue builds up an object (in this case ’None’) to return. } Department of Computer Science — University of San Francisco – p.5/?? Department of Computer Science — University of San Francisco – p.6/?? 17-5: Hello World 17-6: Hello World We also need to provide a mapping between method names and the C functions that implement them. Finally, we need some code to initialize and name the module: /* List of all functions in the module */ static PyMethodDef hellomethods[] = { {"HelloWorld", wrap_HelloWorld, METH_VARARGS }, { NULL, NULL } }; /* Module initialization function */ void inithello(void) { Py_InitModule("hello", hellomethods); } Department of Computer Science — University of San Francisco – p.8/?? Department of Computer Science — University of San Francisco – p.7/?? 17-7: Building Hello World 17-8: Dealing with input arguments Now we need to compile this into a dynamically loadable module. (.dll or .so, depending on your platform) Translating input arguments from Python to C is a little trickier: Python has a module called disutils that will make this easy. void HelloWorld2(char *name) { printf("Hello %s\n", name); } create a setup.py that will build and link the C code into a loadable Python module. You may need to copy the resulting module into the current directory. Department of Computer Science — University of San Francisco – p.9/?? 17-9: Dealing with input arguments Our wrapper function needs to be able to create C structures corresponding to Python objects. Arguments are provided in a tuple, so we use Py_ParseTuple to turn them into C structures. PyObject *wrap_Hello2(PyObject *self, PyObject *args) { char *name; if (!PyArg_ParseTuple(args, "s", &name)) return NULL; HelloWorld2(name); return Py_BuildValue(""); } Department of Computer Science — University of San Francisco – p.10/?? 17-10: Dealing with return values Most interesting functions also return something. We need to convert C types back into Python objects Py_BuildValue() does this ’i’ indicates an integer type ’s’ indicates one argument that is a string. Department of Computer Science — University of San Francisco – p.11/?? Department of Computer Science — University of San Francisco – p.12/?? 17-12: 17-11: Dealing with return values We can also return multiple values by putting them in a tuple. Automatically generating wrappers Writing interfaces by hand is fine for simple examples. For large or complex pieces of code, it gets very tedious. Debugging can be hard Easy to introduce errors PyObject *wrap_gcdmult(PyObject *self, PyObject *args) { int x,y,g; if(!PyArg_ParseTuple(args, "ii", &x, &y)) return NULL; g = gcd(x, y); return Py_BuildValue("ii", g, y); } Luckily, there are programs that automatically generate interfaces. We’ll look at SWIG Department of Computer Science — University of San Francisco – p.13/?? 17-13: Department of Computer Science — University of San Francisco – p.14/?? 17-14: SWIG SWIG stands for Simple Wrapper Interface Generator Create an interface file: Connects C/C++ programs to Perl, Python, Ruby, Tcl, C#, Java %module example1 extern int factorial(int n); You define functions and variables in an intermediate language and SWIG generates wrapper code. Run SWIG: swig -python example1.i SWIG example build object modules: gcc -c example1.c example1_wrap.c -I/usr/include/python2.3 Link into a shared library: gcc -shared example1.o example1_wrap.o -o _example1.so Department of Computer Science — University of San Francisco – p.16/?? Department of Computer Science — University of San Francisco – p.15/?? 17-15: Working with existing libraries SWIG can also parse existing C header files This works very nicely for wrapping existing code. 17-16: SWIG SWIG can make interfacing with an existing library very simple. We’re jsut scraping the surface of what can be done with SWIG Very nice for complex data access Arrays, structs, etc. Goal: give you a taste of the way in which scripting languages can interact with ’systems’ languages. Lets you use Python for its strengths (control, data flow) and C for its strengths (efficiency). Department of Computer Science — University of San Francisco – p.17/?? Department of Computer Science — University of San Francisco – p.18/??