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
Programming Language Paradigms Extending Python with C Chris Brooks Department of Computer Science University of San Francisco Department of Computer Science — University of San Francisco – p.1/?? 17-0: Using C code from Python Sometimes, you might want to call C/C++ code from Python. What are some examples? Department of Computer Science — University of San Francisco – p.2/?? 17-1: Using C code from Python Sometimes, you might want to call C/C++ code from Python. Optimize performance Interface with a third-party package Integrate legacy code into a new application. Department of Computer Science — University of San Francisco – p.3/?? 17-2: Using C code from Python There are two approaches to combining C ond Python Write wrapper code by hand. Use an automatic wrapper generator We’ll take a brief look at each. Department of Computer Science — University of San Francisco – p.4/?? 17-3: Hello World Let’s start with Hello World. No inputs or outputs, just a function to be called: /* function to be wrapped */ void HelloWorld () { printf("Hello World\n"); } Department of Computer Science — University of San Francisco – p.5/?? 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(""); } Py_BuildValue builds up an object (in this case ’None’) to return. Department of Computer Science — University of San Francisco – p.6/?? 17-5: Hello World We also need to provide a mapping between method names and the C functions that implement them. /* List of all functions in the module */ static PyMethodDef hellomethods[] = { {"HelloWorld", wrap_HelloWorld, METH_VARARGS }, { NULL, NULL } }; Department of Computer Science — University of San Francisco – p.7/?? 17-6: Hello World Finally, we need some code to initialize and name the module: /* Module initialization function */ void inithello(void) { Py_InitModule("hello", hellomethods); } Department of Computer Science — University of San Francisco – p.8/?? 17-7: Building Hello World Now we need to compile this into a dynamically loadable module. (.dll or .so, depending on your platform) Python has a module called disutils that will make this easy. 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-8: Dealing with input arguments Translating input arguments from Python to C is a little trickier: void HelloWorld2(char *name) { printf("Hello %s\n", name); } Department of Computer Science — University of San Francisco – p.10/?? 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(""); } ’s’ indicates one argument that is a string. Department of Computer Science — University of San Francisco – p.11/?? 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 Department of Computer Science — University of San Francisco – p.12/?? 17-11: Dealing with return values We can also return multiple values by putting them in a tuple. 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); } Department of Computer Science — University of San Francisco – p.13/?? 17-12: 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 Luckily, there are programs that automatically generate interfaces. We’ll look at SWIG Department of Computer Science — University of San Francisco – p.14/?? 17-13: SWIG SWIG stands for Simple Wrapper Interface Generator Connects C/C++ programs to Perl, Python, Ruby, Tcl, C#, Java You define functions and variables in an intermediate language and SWIG generates wrapper code. Department of Computer Science — University of San Francisco – p.15/?? 17-14: SWIG example Create an interface file: %module example1 extern int factorial(int n); Run SWIG: swig -python example1.i 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/?? 17-15: Working with existing libraries SWIG can also parse existing C header files This works very nicely for wrapping existing code. We’re jsut scraping the surface of what can be done with SWIG Goal: give you a taste of the way in which scripting languages can interact with ’systems’ languages. Department of Computer Science — University of San Francisco – p.17/?? 17-16: SWIG SWIG can make interfacing with an existing library very simple. Very nice for complex data access Arrays, structs, etc. 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.18/??