Download presentation
Presentation is loading. Please wait.
1
Python C API overview References: http://docs.python.org/3.2/extending/index.html#extending-index http://docs.python.org/3.2/c-api/
2
Two uses of the Python/C API 1.Extending – Write a dll (.pyd), which exports an initialization function a list of "things" in the module – classes – functions – variables – You can import this just like any (pure) python module – Use the c types / functions in your program import mymodule mymodule.fun(4.1) # A c-function – Many python modules are built this way math pygame numpy …
3
Two uses of the Python/C API 2.Embedding – Create a python interpreter inside a C program (executable) – Can execute python code Usually from a file Possibly from strings hard-coded, generated by the program. – Need to convert to/from python types – Usually interacts with other C/C++ constructs in the executable.
4
The Python / C API A ton of functions. Used in both extensions and embedding. Where are they? – Prototypes (.h) c:\pythonXY\include – Code (.lib) c:\pythonXY\libs\python32.lib – Dll (.dll) c:\pythonXY\DLLs\python3.dll Only necessary if embedding Debug vs. Release – The pre-built (windows) binary only include Release builds – If you want Debug dll's and.lib's you have to build from source.
5
API Naming convention PyXXX_YYY – (Python) class XXX, functionYYY – e.g. PyTuple_Size(…) Py_ZZZ – Global function ZZZ – e.g. Py_Compile(…)
6
PyObject's Literally everything in Python is a PyObject* – Int ref-count (more on this shortly) – A type structure – Any other data e.g. for tuples, they have a length attribute. The python interpreter owns all objects – The user just has references to them – The first time it is referenced, python malloc's it. – When the refcnt reaches 0, it eventually gets free'd – In (normal) python this is done for us… – …but in the C API we have to manage it.
7
RefCounting Take a simple example def foo(a): return a[0] ** 2 + a[1] ** 2 x = [3, 2] y = [foo(x), 3.2] z = y z = None Line 1 – 2 creates a new function object. Line 3 creates a new list x. Line 4 calls foo. o a and x refer to the same list (refcnt is 2) o Creates another float (13.0) and returns it o a goes out of scope – the refcnt on the list is now 1 o The 13.0 and 3.2 are part of a new list object (refcnt = 1) Line 5 makes a second reference to the list (Refcnt = 2) Line 6 decreases the refcnt on the list.
8
RefCounting, cont. …In the C API, you have to manually do it. – Memory Leaks (if you forget to decrement a ref-count) – Invalid memory access (if you forget to increment, and then the object is destroyed) Three functions Py_INCREF(PyObject*); Py_DECREF(PyObject*); Py_XDECREF(PyObject*); // Like previous, but has a NULL- check
9
When to modify Ref-cnts Look in the C/API documentation – New Reference e.g. PyLong_FromLong(long v) You own a ref-count to it. Make sure to call Py_DECREF when done. – Borrowed Reference e.g. PyList_GetItem(PyObject * list, Py_ssize_t index) Someone else holds a reference Don't call DECREF (unless you called INCREF on it) – Stolen Reference e.g. PyTuple_SetItem(PyObject * tuple, Py_ssize_t index, PyObject * item); You usually have created the PyObject item and own a reference to it. After calling the above func, the tuple stole your reference to item, so don't call DECREF on it.
10
Converting / Creating variables Integers – C => Python PyObject * PyLong_FromLong(int i); A new reference – make sure you DECREF it! – Python => C int PyLong_AsLong(PyObject*); float PyLong_AsDouble(PyObject*); … – Determining if a PyObject is a (python) int int PyLong_Check(PyObject*); // 1 if it is, 0 if not
11
Converting / Creating variables, cont. Floats – C => Python PyObject * PyFloat_FromDouble(double d); A new reference – make sure you DECREF it! – Python => C double PyFloat_AsDouble(PyObject*); – Determining if a PyObject* is a (python) float int PyFloat_Check(PyObject*); // 1 if it is.
12
Converting / Creating variables, cont. Strings – A bit more complicated because python 3.x uses unicode internally, not ANSI (char*) strings. – C => Python PyObject * PyUnicode_FromString(char * s); A new reference – make sure you DECREF it! – Python => C char temps[256]; // PObj is the object (in python) we want to convert PyObject * pBytesObj = PyUnicode_AsUTF8String(pObj); if (pBytesObj) { strcpy(temps, PyBytes_AsString(pBytesObj)); Py_DECREF(pBytesObj); } – Determining if a PyObject* is a (python) unicode object. int PyUnicode_Check(PyObject*); // 1 if it is.
13
Tuples Determining if a PyObject is a tuple int PyTuple_Check(PyObject*); // 1 if it is. Creating a new tuple PyObject * PyTuple_New(Py_ssize_t len); – Inserting objects into a new tuple PyTuple_SetItem( PyObject * tup, Py_ssize_t index, PyObject * item ); – Note: this steals a reference to item Getting the size of a tuple Py_ssize_t PyTuple_Size(PyObject * tup); Getting an element of a tuple PyOBject * PyTuple_GetItem(PyOBject * tup, Py_ssize_t indx); – Note: this borrows a reference to the item (i.e. the tuple still owns a reference, so don't DECREF if)
14
Raising exceptions Something happened in your C++ code and you want to raise a python exception If this is in a method / function, you usually return NULL. It is also a good idea to raise an exception so the (python) user can see what happened. PyErr_SetString(PyExc_ValueError, "You did … wrong."); There a bunch of other PyExc_XYZ objects
15
Handling Exceptions Often a (python API) function fails. – It returns NULL (not helpful) – If usually also sets an exception (helpful) To retrieve the error: void PyErr_Fetch(PyObject ** pType, PyObject ** pValue, PyOBject ** pTraceback); – Note: You need to pass the address of a PyOBject* (use the ampersand) – this function will fill them in. To convert pValue (the error string) to a C-string, use: PyObject * PyObject_Str(myPValue); // New ref – Then convert this (unicode) object to a char * as before.
16
C/C++ extensions IDLE (or other python interpreter) Python code (.py) C/C++ extension (a.pyd file). Can contain: Python interfaces to C "classes" Python interfaces to C functions Python interfaces to C variables
17
Creating a C extension (pyd) Goal: – A new class (written in C) – A new function (written in C) – A variable (written in C) – Access all 3 in python Example.py file (myCMod is a C extension): import myCMod C = myCMod.myClass("Bob") print(C.name) # Bob print(C.timestamp) # 0 C.incTimestamp() print(C.timestamp) # 1 print(myCMod.fact(5)) # 120 print(myCMod.aVariable) # Surprise!
18
Making an extension (pyd) 0. Set up a project – A Win32 console dll (empty) – Put all your code in a single.cpp file – Change output to xyz.pyd (actually a.dll) – Only do a release build (debug can only be run by a debug build of python) – Include includes / libs paths – Link with python32.lib Reference: http://docs.python.org/3.2/extending/index.html#extending-index
19
Making an extension (pyd) 1.Create a C-type ("guts" of a python object) 2.Create methods for the new type – static PyObject * asdfasdf(…) 3.Create an attribute (PyMemberDef) and method (PyMethodDef) structure for the new type 4.Create a "dictionary" (static PyTypeObject) of functions and attributes for the new type 5.Create a C function in the module (factorial) – I'll let you experiment with this 6.Create a C variable in the module – I'll let you experiment with this too… 7.Make a PyModuleDef to package the module 8.Make a "main" function PyMODINIT_FUNC PyInit_mycmod(void) – Note: in place of mycmod, put the name of the pyd file (exactly)
20
Embedding the Interpreter C/C++ Program (.exe) Python DLL Python Interpreter Python code (strings) Python (.py) files Other C/C++ objects
21
Creating the embedded interpreter First, Add any internal C modules – These look just as they did for an extension We aren't building a.dll – they exist solely within the executable Includes: – Define any C classes with Python interfaces – Defining the C methods (return values of PyObject *) – Defining the PyMethodDef structure for the class – Define the PyMethodDef for any stand-alone functions – Define the PyModuleDef structure.
22
Creating the embedded interpreter "Import" the C module into the embedded interpreter: PyImport_AppendInittab(char * modName, PyObject * (*funcPtr)(void)); The second parameter is a function pointer Pass the address of a function created as in the last step of making an extension. – This function creates an returns a (Python) module object – Possibly also adds classes to this module (if applicable) The function should have a prototype of PyObject * PyInit_myMod(void)
23
Creating the embedded interpreter Second, start up the interpreter Py_Initialize() – Note: this interpreter will (only) have modules defined with PyImport_AppendInittab. – To add other modules…??? Third, run the rest of the program – At appropriate times, load and run.py files into the embedded interpreter (more on this shortly) Finally, shut down the interpreter Py_Finalize()
24
Loading / Executing a.py file Load the file into a char * buffer – FILE* of fstream and new / delete Compile the buffer into a code module PyObject * Py_CompileString(char * buff, char * fname, Py_file_input) Import and Execute the code module PyImport_ExecCodeModule(char * name, PyObject * codeMod); – This will run the python code. – If that code references the C functions / classes with Python interfaces, that code will now be run. This will usually interact with the rest of the C structures in the program
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.