test.c
#include <Python.h> //integer int add_one(int a){ return a + 1; } static PyObject * py_add_one(PyObject *self, PyObject *args){ int num; if (!PyArg_ParseTuple(args, "i", &num)) return NULL; //parameter reference //The "i" is a integer, if the "ii" are integers, must input two integer return PyLong_FromLong(add_one(num)); } //string int test_string (char *str) { printf("C_=%s\n", str); return 0; } static PyObject * py_test_str(PyObject *self, PyObject *args){ char *str; if (!PyArg_ParseTuple(args, "s", &str)) return NULL; return PyLong_FromString(str, NULL, 0); //Py_RETURN_NONE; } //array static double total(double* data, int len) { double total = 0.0; int i; for(i=0; i<len; ++i) total += data[i]; return total; } static PyObject *totalDoubles(PyObject *self, PyObject *args) { PyObject* seq; double *dbar; double result; int seqlen; int i; /* get one argument as a sequence */ if(!PyArg_ParseTuple(args, "O", &seq)) return 0; seq = PySequence_Fast(seq, "argument must be iterable"); if(!seq) return 0; /* prepare data as an array of doubles */ seqlen = PySequence_Fast_GET_SIZE(seq); dbar = malloc(seqlen*sizeof(double)); if(!dbar) { Py_DECREF(seq); return PyErr_NoMemory( ); } for(i=0; i < seqlen; i++) { PyObject *fitem; PyObject *item = PySequence_Fast_GET_ITEM(seq, i); if(!item) { Py_DECREF(seq); free(dbar); return 0; } fitem = PyNumber_Float(item); if(!fitem) { Py_DECREF(seq); free(dbar); PyErr_SetString(PyExc_TypeError, "all items must be numbers"); return 0; } dbar[i] = PyFloat_AS_DOUBLE(fitem); Py_DECREF(fitem); } /* clean up, compute, and return result */ Py_DECREF(seq); result = total(dbar, seqlen); free(dbar); return Py_BuildValue("d", result); } static PyMethodDef Methods[] = { {"add_one", py_add_one, METH_VARARGS}, {"test_str", py_test_str, METH_VARARGS}, {"total", totalDoubles, METH_VARARGS}, {NULL, NULL} }; static struct PyModuleDef cModule = { PyModuleDef_HEAD_INIT, "Test", /*module name*/ "", /* module documentation, may be NULL */ -1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */ Methods }; PyMODINIT_FUNC PyInit_Test(void){ return PyModule_Create(&cModule);}setup.py
from distutils.core import setup, Extension
module1 = Extension('Test', sources = ['test.c'])
setup (name = 'Test',
version = '1.0',
description = 'This is a demo package',
ext_modules = [module1])
run
python3 setup.py build
It will create a "Test.cpython-35m-x86_64-linux-gnu.so" in the build directory.Make tt.py in the same directory, and run it by python3 tt.py
import Test as t
import array
x = 1
print(t.add_one(x))
print(t.test_str("123"))
array.array('i')
a = array.array('i', (0 for i in range(0, 10)))
a[0]=1
a[1]=2
print(t.total(a))
ref:1. python的C擴展調用,使用原生的python-C-Api
2. 洞庭散人
3. Translating a Python Sequence into a C Array with the PySequence_Fast Protocol
沒有留言:
張貼留言