例一:ctypes
pycall.c
/***gcc -o libpycall.so -shared -fPIC pycall.c*/
#include <stdio.h>
#include <stdlib.h>
int foo(int a, int b)
{
printf("you input %d and %d\n", a, b);
return a+b;
}
pycall.py
import ctypes
ll = ctypes.cdll.LoadLibrary
lib = ll("./libpycall.so")
res= lib.foo(1, 3)
print ('Result=' ,res)
运行
$ gcc -o libpycall.so -shared -fPIC pycall.c
$ python3 pycall.py
you input 1 and 3
Result= 4
例子二
sumtest.c
/*
* gcc -c -fPIC sumtest.c
*
* gcc -shared -fPIC -o sumtest.so sumtest.o
*
*/
double mysum(double a[], long n){
double sum = 0;
int i;
for(i=0;i<n;i++)
sum += a[i];
return sum;
}
编译后产生动态库sumtest.so
测试
>>> import numpy as np
>>> from ctypes import *
>>> sum_test = np.ctypeslib.load_library("./sumtest.so", ".")
>>> print sum_test.mysum
<_FuncPtr object at 0x7faae6fa6ef0>
>>> sum_test.mysum.argtypes = [POINTER(c_double), c_long]
>>> sum_test.mysum.restype = c_double
>>> x = np.arange(1, 101, 1.0)
>>> sum_test.mysum(x.ctypes.data_as(POINTER(c_double)), len(x))
5050.0
>>> def mysum(x):
... return sum_test.mysum(x.ctypes.data_as(POINTER(c_double)), len(x))
...
>>> x = np.arange(1,11,1.0)
>>> mysum(x[::2])
15.0
>>> quit()
三、c中调用python
(1)例一
/* filename:my_python.c
* gcc my_python.c -o my_python -I/usr/include/python2.7 -lpython2.7
*/
#include <Python.h>
int main(int argc, char *argv[])
{
Py_SetProgramName(argv[0]);
Py_Initialize();
PyRun_SimpleString("from time import time,ctime");
PyRun_SimpleString("print 'Today is',ctime(time())\n");
PyRun_SimpleString("print ('Hello Python in c!'\n)");
Py_Finalize();
return 0;
}
运行:
$ gcc my_python.c -o my_python -I/usr/include/python2.7 -lpython2.7
$ ./my_python
Today is Sat Apr 9 22:00:22 2016
Hello Python in c!
(2)例二
euclid_module.py
def euclid(a, b):
while b:
a, b = b, a%b
return a
euclidpy.c
/**
* @file euclidpy.c
* gcc -Wall -O2 -o euclidpy euclidpy.c -I/usr/include/python2.7 -L/usr/lib -lpython2.7 -Wl,-R/usr/local/lib
*/
#include <Python.h>
#include <stdio.h>
int main()
{
//初始化python
Py_Initialize();
if (!Py_IsInitialized()) {
printf("Python_Initialize failed\n");
return 1;
}
PyObject *pModule = NULL;
PyObject *pFunc = NULL;
PyObject *pArg = NULL;
PyObject *result = NULL;
PyRun_SimpleString("import sys"); //直接执行python语句
PyRun_SimpleString("import sys;sys.path.append('.')");
pModule = PyImport_ImportModule("euclid_module");
if (pModule == NULL) {
printf("import module failed!\n");
return -1;
}
pFunc = PyObject_GetAttrString(pModule, "euclid");
pArg = Py_BuildValue("(i, i)", 120, 48);
//调用函数,并得到python类型的返回值
result =PyEval_CallObject(pFunc,pArg);
//c用来保存c/c++类型的返回值
int c;
//将python类型的返回值转换为c/c++类型
PyArg_Parse(result, "i", &c);
//输出返回值
printf("The Greatest Common Divisor (GCD) is:%d\n", c);
Py_Finalize();
return 0;
}
运行:
$ gcc -Wall -O2 -o euclidpy euclidpy.c -I/usr/include/python2.7 -L/usr/lib -lpython2.7 -Wl,-R/usr/local/lib
$ ./euclidpy
The Greatest Common Divisor (GCD) is:24
注意:
如果不加sys.path.append('.')的话,需要设置环境变量export PYTHONPATH=.:$PYTHONPATH,不如程序运行时找不到euclid_module模块
(3)例三
foo_module.py
def foo_function(a):
return a + 1
my_python1.c
/*
* gcc my_python1.c -o my_python1 -I/usr/include/python2.7 -lpython2.7
*
* */
#include <Python.h>
int foo_function_from_python(int a) {
int res;
PyObject *pModule,*pFunc;
PyObject *pArgs, *pValue;
/* import */
pModule = PyImport_Import(PyString_FromString("foo_module"));
/* great_module.great_function */
pFunc = PyObject_GetAttrString(pModule, "foo_function");
/* build args */
pArgs = PyTuple_New(1);
PyTuple_SetItem(pArgs,0, PyInt_FromLong(a));
/* call */
pValue = PyObject_CallObject(pFunc, pArgs);
res = PyInt_AsLong(pValue);
return res;
}
int main(int argc, char *argv[]) {
Py_Initialize();
PyRun_SimpleString("import sys"); //直接执行python语句
PyRun_SimpleString("import sys;sys.path.append('.')");
printf("The result=%d!\n",foo_function_from_python(2));
Py_Finalize();
}
$ ./my_python1
The result=3!
(4)例四:cython
helloworld.pyx
cdef public SayHello():
return str("hello,world\n")
helloworld_cython.c
/* filename:helloworld_cython.c
* gcc helloworld_cython.c helloworld.c -o helloworld_cython -I/usr/include/python2.7 -lpython2.7
*/
#include <Python.h>
#include "helloworld.h"
int main(int argc, char *argv[]) {
Py_Initialize();
inithelloworld();
printf("%s\n",PyString_AsString(
SayHello()
));
Py_Finalize();
}
其中inithelloworld在helloworld.pyx编译后生成的helloworld.h中定义,用于python2,python3用PyInit_helloworld
运行:
$ cython helloworld.pyx
$ gcc helloworld_cython.c helloworld.c -o helloworld_cython -I/usr/include/python2.7 -lpython2.7
$ ./helloworld_cython
hello,world
再举一例:
great_module.pyx
#cython great_module.pyx
cdef public great_function(a,index):
return a[index]
my_cython.c
/* filename:my_cython.c
* gcc my_cython.c great_module.c -o my_cython -I/usr/include/python2.7 -lpython2.7
*/
#include <Python.h>
#include "great_module.h"
int main(int argc, char *argv[]) {
PyObject *tuple;
Py_Initialize();
initgreat_module();
printf("%s\n",PyString_AsString(
great_function(
PyString_FromString("hello"),
PyInt_FromLong(4)
)
));
tuple = Py_BuildValue("(iis)", 1, 2, "three");
printf("%ld\n",PyInt_AsLong(
great_function(
tuple,
PyInt_FromLong(1)
)
));
printf("%s\n",PyString_AsString(
great_function(
tuple,
PyInt_FromLong(2)
)
));
Py_Finalize();
}
运行结果:
$ ./my_cython
o
2
three
四、c编写python模块
mytest.c
// gcc -shared -fPIC -I /usr/include/python2.7 mytest.c -o mytest.so
#include <Python.h>
static PyObject* add(PyObject* self, PyObject* args){
int a=0;
int b=0;
if(!PyArg_ParseTuple(args,"i|i",&a,&b))
return NULL;
return Py_BuildValue("i", a+b);
}
static PyObject* sub(PyObject* self, PyObject* args){
int a=0;
int b=0;
if(!PyArg_ParseTuple(args,"i|i",&a,&b))
return NULL;
return Py_BuildValue("i", a-b);
}
static PyMethodDef addMethods[]={
{"add", add, METH_VARARGS},
{"sub", sub, METH_VARARGS},
{NULL,NULL,0,NULL}
};
void initmytest(){
Py_InitModule("mytest", addMethods);
}
运行:
gcc -shared -fPIC -I /usr/include/python2.7 mytest.c -o mytest.so
生成python可装载的mytest模块
$ python
Python 2.7.6 (default, Jun 22 2015, 17:58:13)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import mytest
>>> mytest.add(10,20)
30
>>> mytest.sub(10,5)
5