目录
Python扩展模块开发
背景
Python是一种解释运行、面向对象设计的程序语言,具有简洁、优雅开发效率高的优点,同时也存在一定缺点,那就是计算效率不高,有时需要借助计算效率高的语言实现性能要求高的业务场景,C语言在计算效率和使用方便的程度下,堪称是最好的选择,以下是基于C扩展Python的实现讲解,提供支持C直接操作Python对象内存,达到零拷贝的特点。
具体实现
模块声明
static struct PyModuleDef test_module = {
PyModuleDef_HEAD_INIT,
"test_module",
NULL,
-1,
methods
};
模块初始化
PyMODINIT_FUNC PyInit_test_module(void)
{
return PyModule_Create(&test_module);
}
模块方法声明
static PyMethodDef methods[] = {
{"py_init", py_init, METH_VARARGS, "py_init"},
{"py_test1", py_test1, METH_VARARGS, "py_test1"},
{"py_test2", py_test2, METH_VARARGS, "py_test2"},
{"py_test3", py_test3, METH_VARARGS, "py_test3"},
{"py_uninit", py_uninit, METH_VARARGS, "py_uninit"},
{NULL, NULL, 0, NULL}
};
方法实现
初始化接口实现
static PyObject* py_init(PyObject* self, PyObject* args)
{
uint32_t ipaddr;
if (!PyArg_ParseTuple(args, "i", &ipaddr)) {
log_write(INFO, "PyArgs_ParseTuple error");
return NULL;
}
int ret = xxx_init(ipaddr);
return Py_BuildValue("i", ret);
}
资源释放接口实现
static PyObject* py_uninit(PyObject* self, PyObject* args)
{
xxx_uninit();
return Py_BuildValue("i", 0);
}
static PyObject* py_test1(PyObject* self, PyObject* args)
{
int ret = 0;
return Py_BuildValue("i", ret);
}
static PyObject* py_test2(PyObject* self, PyObject* args)
{
PyObject* byte_array_obj;
uint32_t test_id = 0;
uint64_t data_size = 0;
if (!PyArg_ParseTuple(args, "iOl", &test_id, &byte_array_obj, &data_size)) {
log_write(INFO, "PyArgs_ParseTuple error");
return NULL;
}
Py_buffer buffer;
uint8_t* data;
int length;
if (PyObject_GetBuffer(byte_array_obj, &buffer, PyBUF_SIMPLE) != 0) {
log_write(INFO, "PyObject_GetBuffer error");
return NULL;
}
data = (uint8_t*)buffer.buf;
length = buffer.len;
int ret = xxx_send(task_id, data, data_size);
log_write(INFO, "ret %d ", ret);
PyBuffer_Release(&buffer);
return Py_BuildValue("i", ret);
}
static PyObject* py_test3(PyObject* self, PyObject* args)
{
PyObject* byte_array_obj;
uint32_t test_id = 0;
if (!PyArg_ParseTuple(args, "iO", &test_id, &byte_array_obj)) {
log_write(INFO, "PyArgs_ParseTuple error");
return NULL;
}
Py_buffer buffer;
uint8_t* data;
int length;
if (PyObject_GetBuffer(byte_array_obj, &buffer, PyBUF_SIMPLE) != 0) {
log_write(INFO, "PyObject_GetBuffer error");
return NULL;
}
data = (uint8_t*)buffer.buf;
length = buffer.len;
int ret = xxx_recv(test_id, data, length);
log_write(INFO, "ret %d ", ret);
PyBuffer_Release(&buffer);
return Py_BuildValue("i", ret);
}
模块编译加载
from distutils.core import setup, Extension
def main():
setup(name="test_module",
version="1.0.0",
description="Python interface for the fputs C library function",
author="xxx",
author_email="xxx@qq.com",
ext_modules=[Extension("test_module", ["test_module.c"])])
if __name__ == "__main__":
main()
sudo python setup.py install
Python调用自定义模块
import test_module
import socket
def main():
ipaddr = int.from_bytes(socket.inet_aton("192.85.1.1"), byteorder='little')
test_id = 1
test_module.py_init(ipaddr)
test_module.py_test1(test_id, "123123145")
test_module.py_test2(test_id)
test_module.py_uninit(ipaddr)
if __name__ == '__main__':
main() main()