python與c/c++相互調用

例一:ctypespython

pycall.clinux

/***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
c++

import ctypes  
ll = ctypes.cdll.LoadLibrary   
lib = ll("./libpycall.so")    
res=  lib.foo(1, 3)
print ('Result=' ,res)

運行app

$ gcc -o libpycall.so -shared -fPIC pycall.cpython2.7

$ python3 pycall.py 函數

you input 1 and 3測試

Result= 4ui

例子二spa

sumtest.crest

/*
 * 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()

3、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

4、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

相關文章
相關標籤/搜索