# Pythonè°ç¨C/C++éç彿°
Pythonè°ç¨Cè¯è¨ç彿°ä¸»è¦å为ä¸é¨åï¼æ åçCè¯è¨å½æ°åºãCè¯è¨Pythonè°ç¨æ¨¡å(wrapper)ãåæ åçPythonè°ç¨ã
## æ åCè¯è¨å½æ°åº
é颿ä¸ç³»åçCè¯è¨å½æ°ã
```c
int add(int m, int n)
{
return m + n;
}
```
[calculate.c](calculate.c)
## æ åPythonè°ç¨
```
$ python
> import calculate
> calculate.add(3, 4)
```
## Cè¯è¨Pythonè°ç¨æ¨¡å
Cè¯è¨Python wrapperï¼pythonåç代ç å¯ä»¥éè¿è¿ä¸ªwrapperæ¥è°ç¨Cè¯è¨å½æ°æä»¶éç彿°ã
è¿ä¸ªæ¨¡åå为ä¸é¨åï¼å¯¼åºå½æ°ãæ¹æ³å表ååå§å彿°ã
```c
/* Exported function */
static
PyCal_add(PyObject *self, PyObject *args)
{
/* Define variables */
int m, n;
int ret;
PyObject *obj;
/* Parse Python args to C args */
PyArg_ParseTuple(args, "ii", &m, &n);
/* Call C native function */
ret = add(m, n);
/* Convert C variable to Python */
obj = Py_BuildValue("i", ret);
/* Return (converted)Python Object */
return obj;
}
/* Method list */
static PyMethodDef CalMethods[] = {
{"add", PyCal_add, METH_VARARGS, "Add two integer values."},
{NULL, NULL, 0, NULL}
};
/* Initialization function */
PyMODINIT_FUNC
initcalcalate(void)
{
PyObject *m;
m = Py_InitModule("calculate", CalMethods);
if(m == NULL) {
return;
}
}
```
### 导åºå½æ°
è¿æ¥Cè¯è¨å½æ°åPython彿°çä¸é´ä»¶ï¼ç±å®æ¥è¿è¡ç¸äºè½¬æ¢ãæPythonçåæ°è½¬æCçåæ°ä¼ éè¿å»ï¼ç¶ååæCçè¾åºè½¬æ¢æPythonæ ¼å¼è¿åã
* 转æ¢Pythonåæ°ä¸ºCè¯è¨ç±»å
è¯¥å½æ°ç第äºä¸ªåæ°`args`å°±æ¯åçPythonè°ç¨ä¼ éè¿æ¥çåæ°ï¼æ¯ä¸ä¸ªCçPython Tuple Objectï¼éè¦è½¬æ¢ææ åçCè¯è¨æ°æ®ç±»åãç®åçåæ°å¯ä»¥ä½¿ç¨`PyArg_ParseTuple`彿°æ¥è¿è¡è§£æï¼å
¶ä¸ç¬¬äºä¸ªåæ°æ¯Cè¯è¨ä¸ç[ç±»å表示符][c-type-symbol]ï¼ç¤ºä¾ä¸çæææ¯è¿ä¸ªPythonä¼ è¿æ¥çåæ°å
å«ä¸¤ä¸ªæ´åï¼intï¼æ°å¼å¹¶ä¸åå«èµå¼ç»månã
夿ç¹çåæ°å°±éè¦ç¨`PyTuple_GetItem`è¿è¡è§£æäºï¼æ¯å¦argsåå«å
å«äºä¸ä¸ªintååä¸ä¸ªåå
¸ç±»åæ°æ®å°±éè¦å¦ä¸æä½ï¼
```
int m;
PyObject *dict = NULL;
PyObject int_m = NULL; /* int_m is a PyInt_Type */
int_m = PyTuple_GetItem(args, 0);
m = PyInt_AsLong(int_m);
dict = PyTuple_GetItem(args, 1);
```
æ¤å¤çPyObject dictåå¯ä»¥ä½¿ç¨PyDict_GetItemString(dict, key)æ¥è§£æï¼å¦æè¿ä¸ªdictçkey䏿¯å符串ï¼å¯ä»¥ä½¿ç¨PyDict_GetItem(dict, PyObjectKey)ã
* 转æ¢Cè¯è¨æ°æ®ä¸ºPythonç±»åå¹¶è¿å
ç®åçCè¯è¨æ°æ®å¯ä»¥ä½¿ç¨`Py_BuildValue`æ¥è½¬æ¢ï¼ç¤ºä¾ä¸`obj = Py_BuildValue("i", ret)`ææå°±æ¯å°retè½¬æ¢æPythonçint Objectã
夿çï¼æ¯å¦è¿åå¼ç±»åæ¯listï¼å¯ä»¥ç¨`PyList_SetItem`æ¥è½¬æ¢ï¼å¦è¿ä¸ªè¿åçlistä¸ç¬¬ä¸ä¸ªå¼æ¯å符串第äºä¸ªæ¯dictï¼
```c
PyObject *list = NULL;
PyObject *dict = NULL;
PyDict_SetItemString(dict, 'key', PyObjectValue);
PyList_SetItem(list, 0, PyObjectStringValue); /* use PyString_FromString to
convert c string to python String */
PyList_SetItem(list, 1, dict);
return list;
```
[calculate_module.c](calculate_module.c)
[å¨ParseTupleåPy_BuildValueä¸å¯ä»¥ä½¿ç¨çCç±»å][c-type-symbol]
[Pythonçç±»åææ ·åCçæ å°][python-object-type]
[c-type-symbol]: https://docs.python.org/2.7/c-api/arg.html
[python-object-type]: https://docs.python.org/2.7/c-api/concrete.html
### æ¹æ³å表ååå§å彿°
ä½ C彿°åºä¸ææå½æ°é½éè¦åå°è¿éé¢ï¼å¦ä¸ï¼
```c
static PyMethodDef CalMethods[] = {
{"add", PyCal_add, METH_VARARGS, "Add two integer values."},
{"square", PyCal_square, METH_VARARGS, "Square one integer value."},
/* ... */
{NULL, NULL, 0, NULL}
};
```
[åè](https://docs.python.org/2.7/extending/extending.html#the-module-s-method-table-and-initialization-function)
## ç¼è¯é¾æ¥
```
$ gcc -fpic -c -I /usr/include/python2.7 \
-I /usr/lib/python2.7/config-x86_64-linux-gnu calculate_module.c
$ gcc -shared -o calculate.so calculate_module.o
$ python
> import calculate
> calculate.add(3, 4)
```
gdbé»è®¤ä¼åäºç¼è¯é项ï¼è¿ä¼å¯¼è´ä½ è°è¯æ¶åºç°è¡å·ä¸å¯¹çé®é¢ï¼è¿æ¶ä½ éè¦å¨gccç¼è¯æ¶å ä¸`-O0`æ¥ç¦ç¨ä¼åæ¥ä¿è¯è°è¯æ¶è¡å·ä¸æºæä»¶ä¿æä¸è´ã
## gdbè°è¯pythonèæ¬åc module
```
# gdb python
(gdb) b PyCal_add
(gdb) dir /path/to/caculate_module_dir
(gdb) run test.py
(gdb) l
(gdb) n
(gdb) n
(gdb) p xx
```
## åè龿¥
1.