python与c/c++相互调用

左心房为你撑大大i 提交于 2019-12-09 20:16:05

例一: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 `pkg-config --cflags --libs python` 

$ ./my_python 

Today is Sat Apr  9 22:00:22 2016

Hello Python in c!

mingw环境:

D:\prg\py\mypyc>gcc my_python.c -o my_python  -IC:\Users\wangxw\AppData\Local\Programs\Python\Python37\include -LC:\Users\wangxw\AppData\Local\Programs\Python\Python37\libs -lpython37

D:\prg\py\mypyc>my_python.exe
Today is Sun Nov 24 19:16:34 2019
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 -lpython2.7
 * gcc -Wall -O2 -o euclidpy euclidpy.c `pkg-config --cflags --libs python` 
 */ 
#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

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!