C擴(kuò)展實(shí)踐
因?yàn)樾阅艿纫恍┰颍M肅來擴(kuò)展python。有多種方法,例如:
- ctypes調(diào)用so
- cython
- python接口的C函數(shù)
這里闡述最后一種方式的實(shí)現(xiàn)。
-
首先需要 #include
- 需要實(shí)現(xiàn)下面三個函數(shù):
static PyObject *funcName(PyObject *self, PyObject *args)
/* 函數(shù)定義 */
static PyMethodDef methodsList[]
/* 方法映射 */
PyMODINIT_FUNC initModule()
/* Module初始化(python3 Module的定義和初始化略有不同,見下面示例代碼) */
完整代碼:
#include
#include
#define PI acos(-1)
#if PY_MAJOR_VERSION >= 3
#define PY3K
#endif
void initcmath(void); /* Forward */
main(int argc, char **argv)
{
/* Pass argv[0] to the Python interpreter */
Py_SetProgramName(argv[0]);
/* Initialize the Python interpreter. Required. */
Py_Initialize();
/* Add a static module */
initcmath();
/* Define sys.argv. It is up to the application if you
want this; you can also leave it undefined (since the Python
code is generally not a main program it has no business
touching sys.argv...)
If the third argument is true, sys.path is modified to include
either the directory containing the script named by argv[0], or
the current working directory. This can be risky; if you run
an application embedding Python in a directory controlled by
someone else, attackers could put a Trojan-horse module in the
directory (say, a file named os.py) that your application would
then import and run.
*/
PySys_SetArgvEx(argc, argv, 0);
/* Do some application specific code */
printf("Hello, brave new world\n\n");
/* Execute some Python statements (in module __main__) */
PyRun_SimpleString("import sys\n");
PyRun_SimpleString("print sys.builtin_module_names\n");
PyRun_SimpleString("print sys.modules.keys()\n");
PyRun_SimpleString("print sys.executable\n");
PyRun_SimpleString("print sys.argv\n");
/* Note that you can call any public function of the Python
interpreter here, e.g. call_object(). */
/* Some more application specific code */
printf("\nGoodbye, cruel world\n");
/* Exit, cleaning up the interpreter */
Py_Exit(0);
/*NOTREACHED*/
}
int fastfactorial(int n){
if(n<=1)
return 1;
else
return n * fastfactorial(n-1);
}
double calculatearea(float r){
double s;
float r1, r2, r3, r4, r5;
r1 = cosf(r);
r2 = sinf(r);
r3 = log10(r);
r4 = PI;
r5 = 666.666;
r = (((r1 + r2) - r3) * r4)/r5;
s = PI * pow(r, 2);
return s;
}
static PyObject* factorial(PyObject* self, PyObject* args){
int n;
if (!PyArg_ParseTuple(args,"i",&n))
return NULL;
int result = fastfactorial(n);
return Py_BuildValue("i",result);
}
static PyObject* do_calculation(PyObject* self, PyObject* args){
float n;
if (!PyArg_ParseTuple(args,"f",&n))
return NULL;
double result = calculatearea(n);
return Py_BuildValue("d",result);
}
static PyMethodDef mainMethods[] = {
{"factorial", factorial, METH_VARARGS, "Calculate the factorial of n"},
{"do_calculation", do_calculation, METH_VARARGS, "Calculate the area of r"},
{NULL, NULL, 0, NULL}
};
#ifdef PY3K
// module definition structure for python3
static PyModuleDef cmath = {
PyModuleDef_HEAD_INIT,
"cmath","Factorial Calculation",
-1,
mainMethods
};
PyMODINIT_FUNC PyInit_cmath(void){
return PyModule_Create(&cmath);
}
#else
// module initializer for python2
PyMODINIT_FUNC initcmath(void) {
// PyImport_AddModule("factorial");
(void) Py_InitModule("cmath", mainMethods);
}
#endif
編譯(使用distutils):
from distutils.core import setup, Extension
factorial_module = Extension('cmath', sources=['cmath.c'])
setup(name='MathExtension',
version='1.0',
description='This is a math package',
ext_modules=[factorial_module]
)
性能對比
使用上面完整代碼中的calculatearea做運(yùn)算性能對比,在python中做同樣實(shí)現(xiàn):
import cmath
import timeit
import math
def do_calculation(r):
r1 = math.cos(r)
r2 = math.sin(r)
r3 = math.log10(r)
r4 = math.pi
r5 = 666.666
r = (((r1 + r2) - r3) * r4)/r5
return math.pi * r * r
if __name__ == '__main__':
print do_calculation(555.555)
print cmath.do_calculation(555.555)
# print sys.modules['__main__']
#
radius = 666.666
num = 10000000
t = timeit.Timer("cmath.do_calculation(%f)" % (radius), "import cmath")
print "C function", t.timeit(num), "sec"
t2 = timeit.Timer("sys.modules['__main__'].do_calculation(%f)" % (radius))
print "Python function", t2.timeit(num), "sec"
執(zhí)行10000000次對比耗時:
OK,C實(shí)現(xiàn)的方案相同運(yùn)算速度遠(yuǎn)快于python實(shí)現(xiàn),目的達(dá)到。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
