- Python C/C++扩展库
- 附录-参考资料
- 0-Python的C/C++扩展库_模块和函数
- 0-1完成python的c扩展库模块入口创建和扩展函数代码
- 0-2Python源码PyObject结构分析和引用计数代码分析
- 0-3PyLongObject与PyObject关系讲解及源码分析
- 0-4基于PyArg_ParseTuple给扩展库传递整形参数
- 0-5传递浮点数并通过PyFloat_Check检测参数类型
- 0-6PyUnicodeObject结构分析和扩展库返回字符串
- 0-7扩展库传递关键字参数METH_KEYWORDS
- 0-8扩展库传递一维和二维元组tuple参数并分析tuple源码
- 0-9扩展库返回一维和二维元组tuple
- 0-10扩展库读取list参数遍历显示并检测格式错误设置异常字符
- 0-11扩展库添加_插入_修改和删除list参数中元素
- 0-12扩展库返回新创的list和参数list并对引用计数加一
- 0-13扩展库读取Dictionary参数并处理引用计数解决内存泄漏问题
- 0-14扩展库根据关键字读取字典并清理空间
- 0-15扩展库函数参数遍历字典PyDict_Keys并清理相应空间
- 0-16扩展库PyDict_Next迭代访问字典内容并封装PyObject打印函数
- 0-17扩展库处理dict参数插入修改和删除数据
- 0-18扩展库函数返回dictionary字段
- 1-myproject用到的关键技术
Python C/C++扩展库
附录-参考资料
https://github.com/zpoint/CPython-Internals/blob/master/README_CN.md
https://me.csdn.net/jiedichina
http://www.ffmpeg.club/python.html
https://docs.python.org/3.7/
https://docs.python.org/zh-cn/3.7/c-api/index.html
https://docs.python.org/zh-cn/3.7/extending/index.html#extending-index
https://docs.python.org/zh-cn/3.7/extending/extending.html
https://docs.python.org/zh-cn/3.7/c-api/arg.html#c.PyArg_ParseTupleAndKeywords
https://www.rddoc.com/doc/Python/3.6.0/zh/c-api/structures/
https://python3-cookbook.readthedocs.io/zh_CN/latest/c15/p15_converting_c_string_to_python.html
《Python源码剖析》Python源码剖析-深度探索动态语言核心技术
https://www.jb51.net/books/106825.html
Python源码剖析 [文字版].pdf https://vdisk.weibo.com/s/zKJ5Hm-qtWVsV
https://github.com/spillai/numpy-opencv-converter
https://github.com/yati-sagade/opencv-ndarray-conversion
https://stackoverflow.com/questions/42125084/accessing-opencv-cuda-functions-from-python-no-pycuda
https://www.thinbug.com/q/43838418
https://github.com/Algomorph/pyboostcvconverter
https://pythonextensionpatterns.readthedocs.io/en/latest/index.html
https://www.docs4dev.com/docs/zh/python/3.7.2rc1/all/c-api-arg.html
0-Python的C/C++扩展库_模块和函数
0-1完成python的c扩展库模块入口创建和扩展函数代码
mymod.c
#include "Python.h"
///5 模块函数
static PyObject *testmod(PyObject *self)
{
//返回python的long整形,c语言中引用计数+1,返回值交由python释放,
return PyLong_FromLong(101);
}
///4 模块函数列表
static PyMethodDef mymod_funcs[] = {
{
"testmod", //函数名称
testmod, //函数指针
METH_NOARGS,//参数标识 无参数
"testmod function." //函数说明 help(testmod)
},
{0,0,0,0}
};
///3 模块定义
static PyModuleDef mymod_module = {
PyModuleDef_HEAD_INIT,
"mymod", //模块名
"mymod is first module test", //模块说明 通过help(模块名)
-1, //模块空间,子解释器用,-1不使用
mymod_funcs //模块函数
};
///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名
PyMODINIT_FUNC PyInit_mymod(void)
{
printf("PyInit_mymod\n");
///2 模块创建函数 参数 PyModuleDef
return PyModule_Create(&mymod_module);
}
setup.py
from distutils.core import *
setup(
name="mymod", #打包文件名称
version="1.0",
ext_modules=[Extension("mymod", ["mymod.c"] )]
)
testmod.py
print("Test mymod Module")
import mymod
#print(help(mymod))
print(mymod.testmod())
0-2Python源码PyObject结构分析和引用计数代码分析
PyObject 所有对象都是它的扩展
存放引用计数和对象类型ob_type
include/object.h
typedef struct _object {
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
} PyObject;
_PyObject_HEAD_EXTRA Release下为空,Debug下为链表
Py_ssize_t ob_refcnt; 引用计数
struct _typeobject *ob_type; 结构体对象
0-3PyLongObject与PyObject关系讲解及源码分析
提醒
对于不同的系统,大数能表示的范围不一致,因为数字采用的是unsigned long存放,在不同的系统大小不一致,可以见如下表
其中 windows 64位使用的是 LLP64所以 在window中python数字的最大值也就是4个字节,如果用它来存放64位指针的地址,就会丢失数据。在linux(ubuntu16.04 64)使用的是LP64,,所以数字最大值就是8个字节。
0-4基于PyArg_ParseTuple给扩展库传递整形参数
mymod.c
#include "Python.h"
///5 模块函数
static PyObject *testmod(PyObject *self,PyObject*args)
{
int x = 0;
int y = 0;
//失败会写入异常信息
if (!PyArg_ParseTuple(args, "ii", &x,&y))
{
printf("PyArg_ParseTuple");
return NULL; //会抛出异常
}
printf("PyArg_ParseTuple x = %d y = %d\n", x,y);
//返回python的long整形,c语言中引用计数+1,返回值交由python释放,
return PyLong_FromLong(105);
}
///4 模块函数列表
static PyMethodDef mymod_funcs[] = {
{
"testmod", //函数名称
testmod, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"testmod function." //函数说明 help(testmod)
},
{0,0,0,0}
};
///3 模块定义
static PyModuleDef mymod_module = {
PyModuleDef_HEAD_INIT,
"TestPythonExt", //模块名
"TestPythonExt is first module test", //模块说明 通过help(模块名)
-1, //模块空间,子解释器用,-1不使用
mymod_funcs //模块函数
};
///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名
PyMODINIT_FUNC PyInit_TestPythonExt(void)
{
printf("PyInit_TestPythonExt\n");
///2 模块创建函数 参数 PyModuleDef
return PyModule_Create(&mymod_module);
}
setup.py
from distutils.core import *
setup(
name="TestPythonExt", #打包文件名称
version="1.0",
ext_modules=[Extension("TestPythonExt", ["mymod.c"] )]
)
testmod.py
print("Test TestPythonExt Module")
import TestPythonExt
try:
print(TestPythonExt.testmod(999, 555))
except Exception as e:
print(e)
input()
0-5传递浮点数并通过PyFloat_Check检测参数类型
mymod.c
#include "Python.h"
static PyObject *test_float(PyObject *self, PyObject*arg)
{
printf("test_float\n");
if (PyFloat_Check(arg))
{
double a = PyFloat_AsDouble(arg);
printf("arg type is float ,value = %f \n",a);
}
else
{
printf("arg type is not float\n");
}
return PyLong_FromLong(0);
}
///5 模块函数
static PyObject *testmod(PyObject *self,PyObject*args)
{
int x = 0;
int y = 0;
float z = 0.0;
//失败会写入异常信息
if (!PyArg_ParseTuple(args, "iif", &x,&y,&z))
{
printf("PyArg_ParseTuple");
return NULL; //会抛出异常
}
printf("PyArg_ParseTuple x = %d y = %d z = %f\n", x,y,z);
//返回python的long整形,c语言中引用计数+1,返回值交由python释放,
return PyLong_FromLong(105);
}
///4 模块函数列表
static PyMethodDef mymod_funcs[] = {
{
"testmod", //函数名称
testmod, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"testmod function." //函数说明 help(testmod)
},
{
"test_float", //函数名称
test_float, //函数指针
METH_O, // 只有一个参数,参数标识 无参数 METH_VARARGS METH_NOARGS METH_O
"test_float function." //函数说明 help(testmod)
},
{0,0,0,0}
};
///3 模块定义
static PyModuleDef mymod_module = {
PyModuleDef_HEAD_INIT,
"TestPythonExt", //模块名
"TestPythonExt is first module test", //模块说明 通过help(模块名)
-1, //模块空间,子解释器用,-1不使用
mymod_funcs //模块函数
};
///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名
PyMODINIT_FUNC PyInit_TestPythonExt(void)
{
printf("PyInit_TestPythonExt\n");
///2 模块创建函数 参数 PyModuleDef
return PyModule_Create(&mymod_module);
}
setup.py
from distutils.core import *
setup(
name="TestPythonExt", #打包文件名称
version="1.0",
ext_modules=[Extension("TestPythonExt", ["mymod.c"] )]
)
testmod.py
print("Test TestPythonExt Module")
#import TestPythonExt
from TestPythonExt import *
#print(help(mymod))
try:
#print(TestPythonExt.testmod(999, 555,33.44))
print(testmod(999, 555,33.44))
test_float("xx")
test_float(66.)
except Exception as e:
print(e)
input()
0-6PyUnicodeObject结构分析和扩展库返回字符串
mymod.c
#include "Python.h"
static PyObject *test_string(PyObject *self, PyObject*args)
{
char *str = 0;
//str 会指向python内部空间
if (!PyArg_ParseTuple(args, "s", &str))
{
return NULL;
}
//传递过来的字符串是utf-8格式,控制台默认GBK,中文乱码
printf("PyArg_ParseTuple return string = %s \n", str);
//如果有中文,要把代码设置为utf-8格式
//分配空间,引用计数+1 ,交给python解释器释放
return PyUnicode_FromString("PyUnicode_FromString in c return ");
}
static PyObject *test_float(PyObject *self, PyObject*arg)
{
printf("test_float\n");
if (PyFloat_Check(arg))
{
double a = PyFloat_AsDouble(arg);
printf("arg type is float ,value = %f \n",a);
}
else
{
printf("arg type is not float\n");
}
return PyLong_FromLong(0);
}
///5 模块函数
static PyObject *testmod(PyObject *self,PyObject*args)
{
int x = 0;
int y = 0;
float z = 0.0;
//失败会写入异常信息
if (!PyArg_ParseTuple(args, "iif", &x,&y,&z))
{
printf("PyArg_ParseTuple");
return NULL; //会抛出异常
}
printf("PyArg_ParseTuple x = %d y = %d z = %f\n", x,y,z);
//返回python的long整形,c语言中引用计数+1,返回值交由python释放,
return PyLong_FromLong(105);
}
///4 模块函数列表
static PyMethodDef mymod_funcs[] = {
{
"testmod", //函数名称
testmod, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"testmod function." //函数说明 help(testmod)
},
{
"test_float", //函数名称
test_float, //函数指针
METH_O, // 只有一个参数,参数标识 无参数 METH_VARARGS METH_NOARGS METH_O
"test_float function." //函数说明 help(testmod)
},
{
"test_string", //函数名称
test_string, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"test_string function." //函数说明 help(testmod)
},
{0,0,0,0}
};
///3 模块定义
static PyModuleDef mymod_module = {
PyModuleDef_HEAD_INIT,
"TestPythonExt", //模块名
"TestPythonExt is first module test", //模块说明 通过help(模块名)
-1, //模块空间,子解释器用,-1不使用
mymod_funcs //模块函数
};
///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名
PyMODINIT_FUNC PyInit_TestPythonExt(void)
{
printf("PyInit_TestPythonExt\n");
///2 模块创建函数 参数 PyModuleDef
return PyModule_Create(&mymod_module);
}
setup.py
from distutils.core import *
setup(
name="TestPythonExt", #打包文件名称
version="1.0",
ext_modules=[Extension("TestPythonExt", ["mymod.c"] )]
)
testmod.py
print("Test TestPythonExt Module")
#import TestPythonExt
from TestPythonExt import *
#print(help(mymod))
try:
#print(TestPythonExt.testmod(999, 555,33.44))
print(testmod(999, 555,33.44))
test_float("xx")
test_float(66.)
a = test_string("Python string to C++")
print("test_string return type is ",type(a))
print("test_string return= \" ", a,"\"")
except Exception as e:
print(e)
input()
0-7扩展库传递关键字参数METH_KEYWORDS
mymod.c
#include "Python.h"
static PyObject *test_kw(PyObject *self, PyObject*args, PyObject*kw)
{
const char *name = "";
int age = 10;
int score = 60;
static char *keys[] = { "name","age","score",NULL };
if (!PyArg_ParseTupleAndKeywords(args,kw,"s|ii", keys,&name,&age,&score))
{
return NULL; //0 抛出异常
}
printf("Name is %s age is %d score is %d \n", name, age, score);
Py_RETURN_NONE; //None
}
static PyObject *test_string(PyObject *self, PyObject*args)
{
char *str = 0;
//str 会指向python内部空间
if (!PyArg_ParseTuple(args, "s", &str))
{
return NULL;
}
//传递过来的字符串是utf-8格式,控制台默认GBK,中文乱码
printf("PyArg_ParseTuple return string = %s \n", str);
//如果有中文,要把代码设置为utf-8格式
//分配空间,引用计数+1 ,交给python解释器释放
return PyUnicode_FromString("PyUnicode_FromString in c return ");
}
static PyObject *test_float(PyObject *self, PyObject*arg)
{
printf("test_float\n");
if (PyFloat_Check(arg))
{
double a = PyFloat_AsDouble(arg);
printf("arg type is float ,value = %f \n",a);
}
else
{
printf("arg type is not float\n");
}
return PyLong_FromLong(0);
}
///5 模块函数
static PyObject *testmod(PyObject *self,PyObject*args)
{
int x = 0;
int y = 0;
float z = 0.0;
//失败会写入异常信息
if (!PyArg_ParseTuple(args, "iif", &x,&y,&z))
{
printf("PyArg_ParseTuple");
return NULL; //会抛出异常
}
printf("PyArg_ParseTuple x = %d y = %d z = %f\n", x,y,z);
//返回python的long整形,c语言中引用计数+1,返回值交由python释放,
return PyLong_FromLong(105);
}
///4 模块函数列表
static PyMethodDef mymod_funcs[] = {
{
"testmod", //函数名称
testmod, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"testmod function." //函数说明 help(testmod)
},
{
"test_float", //函数名称
test_float, //函数指针
METH_O, // 只有一个参数,参数标识 无参数 METH_VARARGS METH_NOARGS METH_O
"test_float function." //函数说明 help(testmod)
},
{
"test_string", //函数名称
test_string, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"test_string function." //函数说明 help(testmod)
},
{
"test_kw", //函数名称
test_kw, //函数指针
METH_VARARGS| METH_KEYWORDS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{0,0,0,0}
};
///3 模块定义
static PyModuleDef mymod_module = {
PyModuleDef_HEAD_INIT,
"TestPythonExt", //模块名
"TestPythonExt is first module test", //模块说明 通过help(模块名)
-1, //模块空间,子解释器用,-1不使用
mymod_funcs //模块函数
};
///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名
PyMODINIT_FUNC PyInit_TestPythonExt(void)
{
printf("PyInit_TestPythonExt\n");
///2 模块创建函数 参数 PyModuleDef
return PyModule_Create(&mymod_module);
}
setup.py
from distutils.core import *
setup(
name="TestPythonExt", #打包文件名称
version="1.0",
ext_modules=[Extension("TestPythonExt", ["mymod.c"] )]
)
testmod.py
print("Test TestPythonExt Module")
#import TestPythonExt
from TestPythonExt import *
#print(help(mymod))
try:
#print(TestPythonExt.testmod(999, 555,33.44))
print(testmod(999, 555,33.44))
test_float("xx")
test_float(66.)
a = test_string("Python string to C++")
print("test_string return type is ",type(a))
print("test_string return= \" ", a,"\"")
test_kw(name="xiaoming1",age=20,score=100)
test_kw(name="xiaoming2")
test_kw("xiaoming3",15,70)
test_kw("xiaoming4",score=150)
except Exception as e:
print(e)
input()
0-8扩展库传递一维和二维元组tuple参数并分析tuple源码
mymod.c
#include "Python.h"
static PyObject *test_tuple(PyObject *self, PyObject*args)
{
//获取元组对象
PyObject *tup = NULL;
if (!PyArg_ParseTuple(args, "O", &tup))
{
return NULL;
}
//元组大小
Py_ssize_t size = PyTuple_Size(tup);
printf("\n=====================================\n");
for (int i = 0; i < size; i++)
{
//元组的元素
PyObject *val = PyTuple_GetItem(tup, i);
//二维元组
if (PyTuple_Check(val))
{
Py_ssize_t s = PyTuple_Size(val);
printf(" ( ");
for (int j = 0; j < s; j++)
{
PyObject *v = PyTuple_GetItem(val, j);
printf("%d ", PyLong_AsLong(v));
}
printf(" ) ");
continue;
}
int r = PyLong_AsLong(val);
printf("%d ", r);
}
Py_RETURN_NONE;
}
static PyObject *test_kw(PyObject *self, PyObject*args, PyObject*kw)
{
const char *name = "";
int age = 10;
int score = 60;
static char *keys[] = { "name","age","score",NULL };
if (!PyArg_ParseTupleAndKeywords(args,kw,"s|ii", keys,&name,&age,&score))
{
return NULL; //0 抛出异常
}
printf("Name is %s age is %d score is %d \n", name, age, score);
Py_RETURN_NONE; //None
}
static PyObject *test_string(PyObject *self, PyObject*args)
{
char *str = 0;
//str 会指向python内部空间
if (!PyArg_ParseTuple(args, "s", &str))
{
return NULL;
}
//传递过来的字符串是utf-8格式,控制台默认GBK,中文乱码
printf("PyArg_ParseTuple return string = %s \n", str);
//如果有中文,要把代码设置为utf-8格式
//分配空间,引用计数+1 ,交给python解释器释放
return PyUnicode_FromString("PyUnicode_FromString in c return ");
}
static PyObject *test_float(PyObject *self, PyObject*arg)
{
printf("test_float\n");
if (PyFloat_Check(arg))
{
double a = PyFloat_AsDouble(arg);
printf("arg type is float ,value = %f \n",a);
}
else
{
printf("arg type is not float\n");
}
return PyLong_FromLong(0);
}
///5 模块函数
static PyObject *testmod(PyObject *self,PyObject*args)
{
int x = 0;
int y = 0;
float z = 0.0;
//失败会写入异常信息
if (!PyArg_ParseTuple(args, "iif", &x,&y,&z))
{
printf("PyArg_ParseTuple");
return NULL; //会抛出异常
}
printf("PyArg_ParseTuple x = %d y = %d z = %f\n", x,y,z);
//返回python的long整形,c语言中引用计数+1,返回值交由python释放,
return PyLong_FromLong(105);
}
///4 模块函数列表
static PyMethodDef mymod_funcs[] = {
{
"testmod", //函数名称
testmod, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"testmod function." //函数说明 help(testmod)
},
{
"test_float", //函数名称
test_float, //函数指针
METH_O, // 只有一个参数,参数标识 无参数 METH_VARARGS METH_NOARGS METH_O
"test_float function." //函数说明 help(testmod)
},
{
"test_string", //函数名称
test_string, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"test_string function." //函数说明 help(testmod)
},
{
"test_kw", //函数名称
test_kw, //函数指针
METH_VARARGS| METH_KEYWORDS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_tuple", //函数名称
test_tuple, //函数指针
METH_VARARGS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{0,0,0,0}
};
///3 模块定义
static PyModuleDef mymod_module = {
PyModuleDef_HEAD_INIT,
"TestPythonExt", //模块名
"TestPythonExt is first module test", //模块说明 通过help(模块名)
-1, //模块空间,子解释器用,-1不使用
mymod_funcs //模块函数
};
///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名
PyMODINIT_FUNC PyInit_TestPythonExt(void)
{
printf("PyInit_TestPythonExt\n");
///2 模块创建函数 参数 PyModuleDef
return PyModule_Create(&mymod_module);
}
setup.py
from distutils.core import *
setup(
name="TestPythonExt", #打包文件名称
version="1.0",
ext_modules=[Extension("TestPythonExt", ["mymod.c"] )]
)
testmod.py
print("Test TestPythonExt Module")
#import TestPythonExt
from TestPythonExt import *
#print(help(mymod))
try:
#print(TestPythonExt.testmod(999, 555,33.44))
print(testmod(999, 555,33.44))
test_float("xx")
test_float(66.)
a = test_string("Python string to C++")
print("test_string return type is ",type(a))
print("test_string return= \" ", a,"\"")
test_kw(name="xiaoming1",age=20,score=100)
test_kw(name="xiaoming2")
test_kw("xiaoming3",15,70)
test_kw("xiaoming4",score=150)
tup = (1,2,4,5,6,7,8,9,10,11)
test_tuple(tup)
tup2 = (1,2,4,5,6,7,8,9,10,11,(99,88,77,66,55))
test_tuple(tup2)
except Exception as e:
print(e)
input()
0-9扩展库返回一维和二维元组tuple
mymod.c
#include "Python.h"
static PyObject *test_tuple(PyObject *self, PyObject*args)
{
//获取元组对象
PyObject *tup = NULL;
if (!PyArg_ParseTuple(args, "O", &tup))
{
return NULL;
}
//元组大小
Py_ssize_t size = PyTuple_Size(tup);
printf("\n=====================================\n");
for (int i = 0; i < size; i++)
{
//元组的元素
PyObject *val = PyTuple_GetItem(tup, i);
//二维元组
if (PyTuple_Check(val))
{
Py_ssize_t s = PyTuple_Size(val);
printf(" ( ");
for (int j = 0; j < s; j++)
{
PyObject *v = PyTuple_GetItem(val, j);
printf("%d ", PyLong_AsLong(v));
}
printf(" ) ");
continue;
}
int r = PyLong_AsLong(val);
printf("%d ", r);
}
//Py_RETURN_NONE;
//返回元组
PyObject *retup = PyTuple_New(10);
PyTuple_SetItem(retup, 0, PyLong_FromLong(102));
PyTuple_SetItem(retup, 1, PyUnicode_FromString("Test Tuple return string "));
//二级元组
PyObject *tup2 = PyTuple_New(3);
PyTuple_SetItem(tup2, 0, PyLong_FromLong(201));
PyTuple_SetItem(retup, 3, tup2);
return retup;
}
static PyObject *test_kw(PyObject *self, PyObject*args, PyObject*kw)
{
const char *name = "";
int age = 10;
int score = 60;
static char *keys[] = { "name","age","score",NULL };
if (!PyArg_ParseTupleAndKeywords(args,kw,"s|ii", keys,&name,&age,&score))
{
return NULL; //0 抛出异常
}
printf("Name is %s age is %d score is %d \n", name, age, score);
Py_RETURN_NONE; //None
}
static PyObject *test_string(PyObject *self, PyObject*args)
{
char *str = 0;
//str 会指向python内部空间
if (!PyArg_ParseTuple(args, "s", &str))
{
return NULL;
}
//传递过来的字符串是utf-8格式,控制台默认GBK,中文乱码
printf("PyArg_ParseTuple return string = %s \n", str);
//如果有中文,要把代码设置为utf-8格式
//分配空间,引用计数+1 ,交给python解释器释放
return PyUnicode_FromString("PyUnicode_FromString in c return ");
}
static PyObject *test_float(PyObject *self, PyObject*arg)
{
printf("test_float\n");
if (PyFloat_Check(arg))
{
double a = PyFloat_AsDouble(arg);
printf("arg type is float ,value = %f \n",a);
}
else
{
printf("arg type is not float\n");
}
return PyLong_FromLong(0);
}
///5 模块函数
static PyObject *testmod(PyObject *self,PyObject*args)
{
int x = 0;
int y = 0;
float z = 0.0;
//失败会写入异常信息
if (!PyArg_ParseTuple(args, "iif", &x,&y,&z))
{
printf("PyArg_ParseTuple");
return NULL; //会抛出异常
}
printf("PyArg_ParseTuple x = %d y = %d z = %f\n", x,y,z);
//返回python的long整形,c语言中引用计数+1,返回值交由python释放,
return PyLong_FromLong(105);
}
///4 模块函数列表
static PyMethodDef mymod_funcs[] = {
{
"testmod", //函数名称
testmod, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"testmod function." //函数说明 help(testmod)
},
{
"test_float", //函数名称
test_float, //函数指针
METH_O, // 只有一个参数,参数标识 无参数 METH_VARARGS METH_NOARGS METH_O
"test_float function." //函数说明 help(testmod)
},
{
"test_string", //函数名称
test_string, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"test_string function." //函数说明 help(testmod)
},
{
"test_kw", //函数名称
test_kw, //函数指针
METH_VARARGS| METH_KEYWORDS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_tuple", //函数名称
test_tuple, //函数指针
METH_VARARGS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{0,0,0,0}
};
///3 模块定义
static PyModuleDef mymod_module = {
PyModuleDef_HEAD_INIT,
"TestPythonExt", //模块名
"TestPythonExt is first module test", //模块说明 通过help(模块名)
-1, //模块空间,子解释器用,-1不使用
mymod_funcs //模块函数
};
///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名
PyMODINIT_FUNC PyInit_TestPythonExt(void)
{
printf("PyInit_TestPythonExt\n");
///2 模块创建函数 参数 PyModuleDef
return PyModule_Create(&mymod_module);
}
setup.py
from distutils.core import *
setup(
name="TestPythonExt", #打包文件名称
version="1.0",
ext_modules=[Extension("TestPythonExt", ["mymod.c"] )]
)
testmod.py
print("Test TestPythonExt Module")
#import TestPythonExt
from TestPythonExt import *
#print(help(mymod))
try:
#print(TestPythonExt.testmod(999, 555,33.44))
print(testmod(999, 555,33.44))
test_float("xx")
test_float(66.)
a = test_string("Python string to C++")
print("test_string return type is ",type(a))
print("test_string return= \" ", a,"\"")
test_kw(name="xiaoming1",age=20,score=100)
test_kw(name="xiaoming2")
test_kw("xiaoming3",15,70)
test_kw("xiaoming4",score=150)
tup = (1,2,4,5,6,7,8,9,10,11)
test_tuple(tup)
tup2 = (1,2,4,5,6,7,8,9,10,11,(99,88,77,66,55))
test_tuple(tup2)
re = test_tuple(tup)
print("\n=============retur===============")
print(re)
except Exception as e:
print(e)
input()
0-10扩展库读取list参数遍历显示并检测格式错误设置异常字符
mymod.c
#include "Python.h"
static PyObject *test_list(PyObject *self, PyObject*args)
{
PyObject *lis1 = NULL;
if (!PyArg_ParseTuple(args, "O", &lis1))
{
return NULL;
}
if (!PyList_Check(lis1))
{
//异常信息
PyErr_SetString(PyExc_Exception, "arg must be list");
return NULL;
}
Py_ssize_t size = PyList_Size(lis1);
for (int i = 0; i < size; i++)
{
PyObject *val = PyList_GetItem(lis1, i);
int r = PyLong_AsLong(val);
printf("%d ", r);
}
return PyLong_FromLong(0);
}
static PyObject *test_tuple(PyObject *self, PyObject*args)
{
//获取元组对象
PyObject *tup = NULL;
if (!PyArg_ParseTuple(args, "O", &tup))
{
return NULL;
}
//元组大小
Py_ssize_t size = PyTuple_Size(tup);
printf("\n=====================================\n");
for (int i = 0; i < size; i++)
{
//元组的元素
PyObject *val = PyTuple_GetItem(tup, i);
//二维元组
if (PyTuple_Check(val))
{
Py_ssize_t s = PyTuple_Size(val);
printf(" ( ");
for (int j = 0; j < s; j++)
{
PyObject *v = PyTuple_GetItem(val, j);
printf("%d ", PyLong_AsLong(v));
}
printf(" ) ");
continue;
}
int r = PyLong_AsLong(val);
printf("%d ", r);
}
//Py_RETURN_NONE;
//返回元组
PyObject *retup = PyTuple_New(10);
PyTuple_SetItem(retup, 0, PyLong_FromLong(102));
PyTuple_SetItem(retup, 1, PyUnicode_FromString("Test Tuple return string "));
//二级元组
PyObject *tup2 = PyTuple_New(3);
PyTuple_SetItem(tup2, 0, PyLong_FromLong(201));
PyTuple_SetItem(retup, 3, tup2);
return retup;
}
static PyObject *test_kw(PyObject *self, PyObject*args, PyObject*kw)
{
const char *name = "";
int age = 10;
int score = 60;
static char *keys[] = { "name","age","score",NULL };
if (!PyArg_ParseTupleAndKeywords(args,kw,"s|ii", keys,&name,&age,&score))
{
return NULL; //0 抛出异常
}
printf("Name is %s age is %d score is %d \n", name, age, score);
Py_RETURN_NONE; //None
}
static PyObject *test_string(PyObject *self, PyObject*args)
{
char *str = 0;
//str 会指向python内部空间
if (!PyArg_ParseTuple(args, "s", &str))
{
return NULL;
}
//传递过来的字符串是utf-8格式,控制台默认GBK,中文乱码
printf("PyArg_ParseTuple return string = %s \n", str);
//如果有中文,要把代码设置为utf-8格式
//分配空间,引用计数+1 ,交给python解释器释放
return PyUnicode_FromString("PyUnicode_FromString in c return ");
}
static PyObject *test_float(PyObject *self, PyObject*arg)
{
printf("test_float\n");
if (PyFloat_Check(arg))
{
double a = PyFloat_AsDouble(arg);
printf("arg type is float ,value = %f \n",a);
}
else
{
printf("arg type is not float\n");
}
return PyLong_FromLong(0);
}
///5 模块函数
static PyObject *testmod(PyObject *self,PyObject*args)
{
int x = 0;
int y = 0;
float z = 0.0;
//失败会写入异常信息
if (!PyArg_ParseTuple(args, "iif", &x,&y,&z))
{
printf("PyArg_ParseTuple");
return NULL; //会抛出异常
}
printf("PyArg_ParseTuple x = %d y = %d z = %f\n", x,y,z);
//返回python的long整形,c语言中引用计数+1,返回值交由python释放,
return PyLong_FromLong(105);
}
///4 模块函数列表
static PyMethodDef mymod_funcs[] = {
{
"testmod", //函数名称
testmod, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"testmod function." //函数说明 help(testmod)
},
{
"test_float", //函数名称
test_float, //函数指针
METH_O, // 只有一个参数,参数标识 无参数 METH_VARARGS METH_NOARGS METH_O
"test_float function." //函数说明 help(testmod)
},
{
"test_string", //函数名称
test_string, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"test_string function." //函数说明 help(testmod)
},
{
"test_kw", //函数名称
test_kw, //函数指针
METH_VARARGS| METH_KEYWORDS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_tuple", //函数名称
test_tuple, //函数指针
METH_VARARGS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_list", //函数名称
test_list, //函数指针
METH_VARARGS,//关键字参数
"test_list function." //函数说明 help(testmod)
},
{0,0,0,0}
};
///3 模块定义
static PyModuleDef mymod_module = {
PyModuleDef_HEAD_INIT,
"TestPythonExt", //模块名
"TestPythonExt is first module test", //模块说明 通过help(模块名)
-1, //模块空间,子解释器用,-1不使用
mymod_funcs //模块函数
};
///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名
PyMODINIT_FUNC PyInit_TestPythonExt(void)
{
printf("PyInit_TestPythonExt\n");
///2 模块创建函数 参数 PyModuleDef
return PyModule_Create(&mymod_module);
}
setup.py
from distutils.core import *
setup(
name="TestPythonExt", #打包文件名称
version="1.0",
ext_modules=[Extension("TestPythonExt", ["mymod.c"] )]
)
testmod.py
print("Test TestPythonExt Module")
#import TestPythonExt
from TestPythonExt import *
#print(help(mymod))
try:
#print(TestPythonExt.testmod(999, 555,33.44))
print(testmod(999, 555,33.44))
test_float("xx")
test_float(66.)
a = test_string("Python string to C++")
print("test_string return type is ",type(a))
print("test_string return= \" ", a,"\"")
test_kw(name="xiaoming1",age=20,score=100)
test_kw(name="xiaoming2")
test_kw("xiaoming3",15,70)
test_kw("xiaoming4",score=150)
tup = (1,2,4,5,6,7,8,9,10,11)
test_tuple(tup)
tup2 = (1,2,4,5,6,7,8,9,10,11,(99,88,77,66,55))
test_tuple(tup2)
re = test_tuple(tup)
print("\n=============retur===============")
print(re)
print("=========test list===========")
try:
test_list(111)
except Exception as e:
print("List Exception",type(e),e)
list1 = [0,1,2,3,4,5,6,7,8,9,10]
test_list(list1)
except Exception as e:
print("Exception",type(e),e)
input()
0-11扩展库添加_插入_修改和删除list参数中元素
mymod.c
#include "Python.h"
static PyObject *test_list(PyObject *self, PyObject*args)
{
PyObject *lis1 = NULL;
if (!PyArg_ParseTuple(args, "O", &lis1))
{
return NULL;
}
if (!PyList_Check(lis1))
{
//异常信息
PyErr_SetString(PyExc_Exception, "arg must be list");
return NULL;
}
Py_ssize_t size = PyList_Size(lis1);
for (int i = 0; i < size; i++)
{
PyObject *val = PyList_GetItem(lis1, i);
int r = PyLong_AsLong(val);
printf("%d ", r);
}
//修改参数list
//结尾处新增
PyList_Append(lis1, PyLong_FromLong(11));
//插入
PyList_Insert(lis1, 4, PyFloat_FromDouble(3.1));
//修改
PyList_SetItem(lis1, 2, PyLong_FromLong(20));
//删除 1开始位置 2结束位置之前
PyList_SetSlice(lis1, 1, 2, 0);
return PyLong_FromLong(0);
}
static PyObject *test_tuple(PyObject *self, PyObject*args)
{
//获取元组对象
PyObject *tup = NULL;
if (!PyArg_ParseTuple(args, "O", &tup))
{
return NULL;
}
//元组大小
Py_ssize_t size = PyTuple_Size(tup);
printf("\n=====================================\n");
for (int i = 0; i < size; i++)
{
//元组的元素
PyObject *val = PyTuple_GetItem(tup, i);
//二维元组
if (PyTuple_Check(val))
{
Py_ssize_t s = PyTuple_Size(val);
printf(" ( ");
for (int j = 0; j < s; j++)
{
PyObject *v = PyTuple_GetItem(val, j);
printf("%d ", PyLong_AsLong(v));
}
printf(" ) ");
continue;
}
int r = PyLong_AsLong(val);
printf("%d ", r);
}
//Py_RETURN_NONE;
//返回元组
PyObject *retup = PyTuple_New(10);
PyTuple_SetItem(retup, 0, PyLong_FromLong(102));
PyTuple_SetItem(retup, 1, PyUnicode_FromString("Test Tuple return string "));
//二级元组
PyObject *tup2 = PyTuple_New(3);
PyTuple_SetItem(tup2, 0, PyLong_FromLong(201));
PyTuple_SetItem(retup, 3, tup2);
return retup;
}
static PyObject *test_kw(PyObject *self, PyObject*args, PyObject*kw)
{
const char *name = "";
int age = 10;
int score = 60;
static char *keys[] = { "name","age","score",NULL };
if (!PyArg_ParseTupleAndKeywords(args,kw,"s|ii", keys,&name,&age,&score))
{
return NULL; //0 抛出异常
}
printf("Name is %s age is %d score is %d \n", name, age, score);
Py_RETURN_NONE; //None
}
static PyObject *test_string(PyObject *self, PyObject*args)
{
char *str = 0;
//str 会指向python内部空间
if (!PyArg_ParseTuple(args, "s", &str))
{
return NULL;
}
//传递过来的字符串是utf-8格式,控制台默认GBK,中文乱码
printf("PyArg_ParseTuple return string = %s \n", str);
//如果有中文,要把代码设置为utf-8格式
//分配空间,引用计数+1 ,交给python解释器释放
return PyUnicode_FromString("PyUnicode_FromString in c return ");
}
static PyObject *test_float(PyObject *self, PyObject*arg)
{
printf("test_float\n");
if (PyFloat_Check(arg))
{
double a = PyFloat_AsDouble(arg);
printf("arg type is float ,value = %f \n",a);
}
else
{
printf("arg type is not float\n");
}
return PyLong_FromLong(0);
}
///5 模块函数
static PyObject *testmod(PyObject *self,PyObject*args)
{
int x = 0;
int y = 0;
float z = 0.0;
//失败会写入异常信息
if (!PyArg_ParseTuple(args, "iif", &x,&y,&z))
{
printf("PyArg_ParseTuple");
return NULL; //会抛出异常
}
printf("PyArg_ParseTuple x = %d y = %d z = %f\n", x,y,z);
//返回python的long整形,c语言中引用计数+1,返回值交由python释放,
return PyLong_FromLong(105);
}
///4 模块函数列表
static PyMethodDef mymod_funcs[] = {
{
"testmod", //函数名称
testmod, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"testmod function." //函数说明 help(testmod)
},
{
"test_float", //函数名称
test_float, //函数指针
METH_O, // 只有一个参数,参数标识 无参数 METH_VARARGS METH_NOARGS METH_O
"test_float function." //函数说明 help(testmod)
},
{
"test_string", //函数名称
test_string, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"test_string function." //函数说明 help(testmod)
},
{
"test_kw", //函数名称
test_kw, //函数指针
METH_VARARGS| METH_KEYWORDS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_tuple", //函数名称
test_tuple, //函数指针
METH_VARARGS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_list", //函数名称
test_list, //函数指针
METH_VARARGS,//关键字参数
"test_list function." //函数说明 help(testmod)
},
{0,0,0,0}
};
///3 模块定义
static PyModuleDef mymod_module = {
PyModuleDef_HEAD_INIT,
"TestPythonExt", //模块名
"TestPythonExt is first module test", //模块说明 通过help(模块名)
-1, //模块空间,子解释器用,-1不使用
mymod_funcs //模块函数
};
///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名
PyMODINIT_FUNC PyInit_TestPythonExt(void)
{
printf("PyInit_TestPythonExt\n");
///2 模块创建函数 参数 PyModuleDef
return PyModule_Create(&mymod_module);
}
setup.py
from distutils.core import *
setup(
name="TestPythonExt", #打包文件名称
version="1.0",
ext_modules=[Extension("TestPythonExt", ["mymod.c"] )]
)
testmod.py
print("Test TestPythonExt Module")
#import TestPythonExt
from TestPythonExt import *
#print(help(mymod))
try:
#print(TestPythonExt.testmod(999, 555,33.44))
print(testmod(999, 555,33.44))
test_float("xx")
test_float(66.)
a = test_string("Python string to C++")
print("test_string return type is ",type(a))
print("test_string return= \" ", a,"\"")
test_kw(name="xiaoming1",age=20,score=100)
test_kw(name="xiaoming2")
test_kw("xiaoming3",15,70)
test_kw("xiaoming4",score=150)
tup = (1,2,4,5,6,7,8,9,10,11)
test_tuple(tup)
tup2 = (1,2,4,5,6,7,8,9,10,11,(99,88,77,66,55))
test_tuple(tup2)
re = test_tuple(tup)
print("\n=============retur===============")
print(re)
print("=========test list===========")
try:
test_list(111)
except Exception as e:
print("List Exception",type(e),e)
list1 = [0,1,2,3,4,5,6,7,8,9,10]
print("\nIn Python begin:",list1)
test_list(list1)
print("\nIn Python end:",list1)
except Exception as e:
print("Exception",type(e),e)
input()
0-12扩展库返回新创的list和参数list并对引用计数加一
mymod.c
#include "Python.h"
static PyObject *test_list(PyObject *self, PyObject*args)
{
PyObject *lis1 = NULL;
if (!PyArg_ParseTuple(args, "O", &lis1))
{
return NULL;
}
if (!PyList_Check(lis1))
{
//异常信息
PyErr_SetString(PyExc_Exception, "arg must be list");
return NULL;
}
Py_ssize_t size = PyList_Size(lis1);
for (int i = 0; i < size; i++)
{
PyObject *val = PyList_GetItem(lis1, i);
int r = PyLong_AsLong(val);
printf("%d ", r);
}
printf("\n");
//修改参数list
//结尾处新增
PyList_Append(lis1, PyLong_FromLong(11));
//插入
PyList_Insert(lis1, 4, PyFloat_FromDouble(3.1));
//修改
PyList_SetItem(lis1, 2, PyLong_FromLong(20));
//删除 1开始位置 2结束位置之前
PyList_SetSlice(lis1, 1, 2, 0);
//返回一个新创建的列表 ,空间交给python释放
/*PyObject *relist = PyList_New(0);
PyList_Append(relist, PyLong_FromLong(100));
PyList_Append(relist, PyLong_FromLong(101));
PyList_Insert(relist, 2, PyLong_FromLong(102));
//返回修改后参数
return relist;*/
//引用计数+1 ,?返回后会被-1
//之所以引用计数+1,是因为作为return会被-1.原本list1在Python端进入,引用计数为1.现在为0
//如果再次在python端调用list1,就会出现问题
Py_XINCREF(lis1);
return lis1;
}
static PyObject *test_tuple(PyObject *self, PyObject*args)
{
//获取元组对象
PyObject *tup = NULL;
if (!PyArg_ParseTuple(args, "O", &tup))
{
return NULL;
}
//元组大小
Py_ssize_t size = PyTuple_Size(tup);
printf("\n=====================================\n");
for (int i = 0; i < size; i++)
{
//元组的元素
PyObject *val = PyTuple_GetItem(tup, i);
//二维元组
if (PyTuple_Check(val))
{
Py_ssize_t s = PyTuple_Size(val);
printf(" ( ");
for (int j = 0; j < s; j++)
{
PyObject *v = PyTuple_GetItem(val, j);
printf("%d ", PyLong_AsLong(v));
}
printf(" ) ");
continue;
}
int r = PyLong_AsLong(val);
printf("%d ", r);
}
//Py_RETURN_NONE;
//返回元组
PyObject *retup = PyTuple_New(10);
PyTuple_SetItem(retup, 0, PyLong_FromLong(102));
PyTuple_SetItem(retup, 1, PyUnicode_FromString("Test Tuple return string "));
//二级元组
PyObject *tup2 = PyTuple_New(3);
PyTuple_SetItem(tup2, 0, PyLong_FromLong(201));
PyTuple_SetItem(retup, 3, tup2);
return retup;
}
static PyObject *test_kw(PyObject *self, PyObject*args, PyObject*kw)
{
const char *name = "";
int age = 10;
int score = 60;
static char *keys[] = { "name","age","score",NULL };
if (!PyArg_ParseTupleAndKeywords(args,kw,"s|ii", keys,&name,&age,&score))
{
return NULL; //0 抛出异常
}
printf("Name is %s age is %d score is %d \n", name, age, score);
Py_RETURN_NONE; //None
}
static PyObject *test_string(PyObject *self, PyObject*args)
{
char *str = 0;
//str 会指向python内部空间
if (!PyArg_ParseTuple(args, "s", &str))
{
return NULL;
}
//传递过来的字符串是utf-8格式,控制台默认GBK,中文乱码
printf("PyArg_ParseTuple return string = %s \n", str);
//如果有中文,要把代码设置为utf-8格式
//分配空间,引用计数+1 ,交给python解释器释放
return PyUnicode_FromString("PyUnicode_FromString in c return ");
}
static PyObject *test_float(PyObject *self, PyObject*arg)
{
printf("test_float\n");
if (PyFloat_Check(arg))
{
double a = PyFloat_AsDouble(arg);
printf("arg type is float ,value = %f \n",a);
}
else
{
printf("arg type is not float\n");
}
return PyLong_FromLong(0);
}
///5 模块函数
static PyObject *testmod(PyObject *self,PyObject*args)
{
int x = 0;
int y = 0;
float z = 0.0;
//失败会写入异常信息
if (!PyArg_ParseTuple(args, "iif", &x,&y,&z))
{
printf("PyArg_ParseTuple");
return NULL; //会抛出异常
}
printf("PyArg_ParseTuple x = %d y = %d z = %f\n", x,y,z);
//返回python的long整形,c语言中引用计数+1,返回值交由python释放,
return PyLong_FromLong(105);
}
///4 模块函数列表
static PyMethodDef mymod_funcs[] = {
{
"testmod", //函数名称
testmod, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"testmod function." //函数说明 help(testmod)
},
{
"test_float", //函数名称
test_float, //函数指针
METH_O, // 只有一个参数,参数标识 无参数 METH_VARARGS METH_NOARGS METH_O
"test_float function." //函数说明 help(testmod)
},
{
"test_string", //函数名称
test_string, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"test_string function." //函数说明 help(testmod)
},
{
"test_kw", //函数名称
test_kw, //函数指针
METH_VARARGS| METH_KEYWORDS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_tuple", //函数名称
test_tuple, //函数指针
METH_VARARGS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_list", //函数名称
test_list, //函数指针
METH_VARARGS,//关键字参数
"test_list function." //函数说明 help(testmod)
},
{0,0,0,0}
};
///3 模块定义
static PyModuleDef mymod_module = {
PyModuleDef_HEAD_INIT,
"TestPythonExt", //模块名
"TestPythonExt is first module test", //模块说明 通过help(模块名)
-1, //模块空间,子解释器用,-1不使用
mymod_funcs //模块函数
};
///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名
PyMODINIT_FUNC PyInit_TestPythonExt(void)
{
printf("PyInit_TestPythonExt\n");
///2 模块创建函数 参数 PyModuleDef
return PyModule_Create(&mymod_module);
}
setup.py
from distutils.core import *
setup(
name="TestPythonExt", #打包文件名称
version="1.0",
ext_modules=[Extension("TestPythonExt", ["mymod.c"] )]
)
testmod.py
print("Test TestPythonExt Module")
#import TestPythonExt
from TestPythonExt import *
#print(help(mymod))
try:
#print(TestPythonExt.testmod(999, 555,33.44))
print(testmod(999, 555,33.44))
test_float("xx")
test_float(66.)
a = test_string("Python string to C++")
print("test_string return type is ",type(a))
print("test_string return= \" ", a,"\"")
test_kw(name="xiaoming1",age=20,score=100)
test_kw(name="xiaoming2")
test_kw("xiaoming3",15,70)
test_kw("xiaoming4",score=150)
tup = (1,2,4,5,6,7,8,9,10,11)
test_tuple(tup)
tup2 = (1,2,4,5,6,7,8,9,10,11,(99,88,77,66,55))
test_tuple(tup2)
re = test_tuple(tup)
print("\n=============retur===============")
print(re)
print("=========test list===========")
try:
test_list(111)
except Exception as e:
print("List Exception",type(e),e)
list1 = [0,1,2,3,4,5,6,7,8,9,10]
print("\nIn Python begin:",list1)
re = test_list(list1)
print("\nIn Python end:",list1)
print(re)
print("list1 id",id(list1), " re id=",id(re))
#返回值会被引用计数-1
test_list(list1)
print(list1)
except Exception as e:
print("Exception",type(e),e)
input()
0-13扩展库读取Dictionary参数并处理引用计数解决内存泄漏问题
mymod.c
#include "Python.h"
static PyObject *test_dict(PyObject *self, PyObject*args)
{
PyObject *dic = NULL;
PyArg_ParseTuple(args, "O", &dic);
if (!PyDict_Check(dic))
{
//设置异常类型和信息,return NULL抛出异常
PyErr_SetString(PyExc_Exception, "arg must be dict");
return NULL;
}
//判断是否由此关键字
//申请空间 引用计数+1 不释放会内存泄漏
PyObject *key = PyUnicode_FromString("name");
int re = PyDict_Contains(dic, key);
Py_XDECREF(key);//引用计数-1 为0清理
if (!re) //无空间操作
{
PyErr_SetString(PyExc_Exception, "key name must be set");
return NULL;
}
return PyLong_FromLong(0);
}
static PyObject *test_list(PyObject *self, PyObject*args)
{
PyObject *lis1 = NULL;
if (!PyArg_ParseTuple(args, "O", &lis1))
{
return NULL;
}
if (!PyList_Check(lis1))
{
//异常信息
PyErr_SetString(PyExc_Exception, "arg must be list");
return NULL;
}
Py_ssize_t size = PyList_Size(lis1);
for (int i = 0; i < size; i++)
{
PyObject *val = PyList_GetItem(lis1, i);
int r = PyLong_AsLong(val);
printf("%d ", r);
}
printf("\n");
//修改参数list
//结尾处新增
PyList_Append(lis1, PyLong_FromLong(11));
//插入
PyList_Insert(lis1, 4, PyFloat_FromDouble(3.1));
//修改
PyList_SetItem(lis1, 2, PyLong_FromLong(20));
//删除 1开始位置 2结束位置之前
PyList_SetSlice(lis1, 1, 2, 0);
//返回一个新创建的列表 ,空间交给python释放
/*PyObject *relist = PyList_New(0);
PyList_Append(relist, PyLong_FromLong(100));
PyList_Append(relist, PyLong_FromLong(101));
PyList_Insert(relist, 2, PyLong_FromLong(102));
//返回修改后参数
return relist;*/
//引用计数+1 ,?返回后会被-1
Py_XINCREF(lis1);
return lis1;
}
static PyObject *test_tuple(PyObject *self, PyObject*args)
{
//获取元组对象
PyObject *tup = NULL;
if (!PyArg_ParseTuple(args, "O", &tup))
{
return NULL;
}
//元组大小
Py_ssize_t size = PyTuple_Size(tup);
printf("\n=====================================\n");
for (int i = 0; i < size; i++)
{
//元组的元素
PyObject *val = PyTuple_GetItem(tup, i);
//二维元组
if (PyTuple_Check(val))
{
Py_ssize_t s = PyTuple_Size(val);
printf(" ( ");
for (int j = 0; j < s; j++)
{
PyObject *v = PyTuple_GetItem(val, j);
printf("%d ", PyLong_AsLong(v));
}
printf(" ) ");
continue;
}
int r = PyLong_AsLong(val);
printf("%d ", r);
}
//Py_RETURN_NONE;
//返回元组
PyObject *retup = PyTuple_New(10);
PyTuple_SetItem(retup, 0, PyLong_FromLong(102));
PyTuple_SetItem(retup, 1, PyUnicode_FromString("Test Tuple return string "));
//二级元组
PyObject *tup2 = PyTuple_New(3);
PyTuple_SetItem(tup2, 0, PyLong_FromLong(201));
PyTuple_SetItem(retup, 3, tup2);
return retup;
}
static PyObject *test_kw(PyObject *self, PyObject*args, PyObject*kw)
{
const char *name = "";
int age = 10;
int score = 60;
static char *keys[] = { "name","age","score",NULL };
if (!PyArg_ParseTupleAndKeywords(args,kw,"s|ii", keys,&name,&age,&score))
{
return NULL; //0 抛出异常
}
printf("Name is %s age is %d score is %d \n", name, age, score);
Py_RETURN_NONE; //None
}
static PyObject *test_string(PyObject *self, PyObject*args)
{
char *str = 0;
//str 会指向python内部空间
if (!PyArg_ParseTuple(args, "s", &str))
{
return NULL;
}
//传递过来的字符串是utf-8格式,控制台默认GBK,中文乱码
printf("PyArg_ParseTuple return string = %s \n", str);
//如果有中文,要把代码设置为utf-8格式
//分配空间,引用计数+1 ,交给python解释器释放
return PyUnicode_FromString("PyUnicode_FromString in c return ");
}
static PyObject *test_float(PyObject *self, PyObject*arg)
{
printf("test_float\n");
if (PyFloat_Check(arg))
{
double a = PyFloat_AsDouble(arg);
printf("arg type is float ,value = %f \n",a);
}
else
{
printf("arg type is not float\n");
}
return PyLong_FromLong(0);
}
///5 模块函数
static PyObject *testmod(PyObject *self,PyObject*args)
{
int x = 0;
int y = 0;
float z = 0.0;
//失败会写入异常信息
if (!PyArg_ParseTuple(args, "iif", &x,&y,&z))
{
printf("PyArg_ParseTuple");
return NULL; //会抛出异常
}
printf("PyArg_ParseTuple x = %d y = %d z = %f\n", x,y,z);
//返回python的long整形,c语言中引用计数+1,返回值交由python释放,
return PyLong_FromLong(105);
}
///4 模块函数列表
static PyMethodDef mymod_funcs[] = {
{
"testmod", //函数名称
testmod, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"testmod function." //函数说明 help(testmod)
},
{
"test_float", //函数名称
test_float, //函数指针
METH_O, // 只有一个参数,参数标识 无参数 METH_VARARGS METH_NOARGS METH_O
"test_float function." //函数说明 help(testmod)
},
{
"test_string", //函数名称
test_string, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"test_string function." //函数说明 help(testmod)
},
{
"test_kw", //函数名称
test_kw, //函数指针
METH_VARARGS| METH_KEYWORDS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_tuple", //函数名称
test_tuple, //函数指针
METH_VARARGS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_list", //函数名称
test_list, //函数指针
METH_VARARGS,//关键字参数
"test_list function." //函数说明 help(testmod)
},
{
"test_dict", //函数名称
test_dict, //函数指针
METH_VARARGS,//关键字参数
"test_dict function." //函数说明 help(testmod)
},
{0,0,0,0}
};
///3 模块定义
static PyModuleDef mymod_module = {
PyModuleDef_HEAD_INIT,
"TestPythonExt", //模块名
"TestPythonExt is first module test", //模块说明 通过help(模块名)
-1, //模块空间,子解释器用,-1不使用
mymod_funcs //模块函数
};
///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名
PyMODINIT_FUNC PyInit_TestPythonExt(void)
{
printf("PyInit_TestPythonExt\n");
///2 模块创建函数 参数 PyModuleDef
return PyModule_Create(&mymod_module);
}
setup.py
from distutils.core import *
setup(
name="TestPythonExt", #打包文件名称
version="1.0",
ext_modules=[Extension("TestPythonExt", ["mymod.c"] )]
)
testmod.py
print("Test TestPythonExt Module")
#import TestPythonExt
from TestPythonExt import *
#print(help(mymod))
try:
#print(TestPythonExt.testmod(999, 555,33.44))
print(testmod(999, 555,33.44))
test_float("xx")
test_float(66.)
a = test_string("Python string to C++")
print("test_string return type is ",type(a))
print("test_string return= \" ", a,"\"")
test_kw(name="xiaoming1",age=20,score=100)
test_kw(name="xiaoming2")
test_kw("xiaoming3",15,70)
test_kw("xiaoming4",score=150)
tup = (1,2,4,5,6,7,8,9,10,11)
test_tuple(tup)
tup2 = (1,2,4,5,6,7,8,9,10,11,(99,88,77,66,55))
test_tuple(tup2)
re = test_tuple(tup)
print("\n=============retur===============")
print(re)
print("=========test list===========")
try:
test_list(111)
except Exception as e:
print("List Exception",type(e),e)
list1 = [0,1,2,3,4,5,6,7,8,9,10]
print("\nIn Python begin:",list1)
re = test_list(list1)
print("\nIn Python end:",list1)
print(re)
print("list1 id",id(list1), " re id=",id(re))
#返回值会被引用计数-1
test_list(list1)
print(list1)
#测试内存消耗
while True:
dic = {"name":"xiaoming"}
test_dict(dic)
except Exception as e:
print("Exception",type(e),e)
input()
0-14扩展库根据关键字读取字典并清理空间
mymod.c
#include "Python.h"
static PyObject *test_dict(PyObject *self, PyObject*args)
{
PyObject *dic = NULL;
PyArg_ParseTuple(args, "O", &dic);
if (!PyDict_Check(dic))
{
//设置异常类型和信息,return NULL抛出异常
PyErr_SetString(PyExc_Exception, "arg must be dict");
return NULL;
}
//判断是否由此关键字
//申请空间 引用计数+1 不释放会内存泄漏
PyObject *key = PyUnicode_FromString("name");
int re = PyDict_Contains(dic, key);
Py_XDECREF(key);//引用计数-1 为0清理
if (!re) //无空间操作
{
PyErr_SetString(PyExc_Exception, "key name must be set");
return NULL;
}
//读取关键字的值
{
PyObject *key = PyUnicode_FromString("name");
PyObject *val = PyDict_GetItem(dic, key); //只做引用
//PyUnicode_AsUnicode(val) 3.3开始过时, 4.0丢弃 空间不明确
wchar_t buf[1024] = { 0 };
PyUnicode_AsWideChar(val, buf, sizeof(buf));
//wprintf("PyDict_GetItem = %s\n", PyUnicode_AsUnicode(val));
wprintf(L"PyDict_GetItem = %s\n", buf);
Py_XDECREF(key);//引用计数-1 为0清理
val = PyDict_GetItemString(dic, "name");
PyUnicode_AsWideChar(val, buf, sizeof(buf));
wprintf(L"PyDict_GetItemString = %s\n", buf);
}
return PyLong_FromLong(0);
}
static PyObject *test_list(PyObject *self, PyObject*args)
{
PyObject *lis1 = NULL;
if (!PyArg_ParseTuple(args, "O", &lis1))
{
return NULL;
}
if (!PyList_Check(lis1))
{
//异常信息
PyErr_SetString(PyExc_Exception, "arg must be list");
return NULL;
}
Py_ssize_t size = PyList_Size(lis1);
for (int i = 0; i < size; i++)
{
PyObject *val = PyList_GetItem(lis1, i);
int r = PyLong_AsLong(val);
printf("%d ", r);
}
printf("\n");
//修改参数list
//结尾处新增
PyList_Append(lis1, PyLong_FromLong(11));
//插入
PyList_Insert(lis1, 4, PyFloat_FromDouble(3.1));
//修改
PyList_SetItem(lis1, 2, PyLong_FromLong(20));
//删除 1开始位置 2结束位置之前
PyList_SetSlice(lis1, 1, 2, 0);
//返回一个新创建的列表 ,空间交给python释放
/*PyObject *relist = PyList_New(0);
PyList_Append(relist, PyLong_FromLong(100));
PyList_Append(relist, PyLong_FromLong(101));
PyList_Insert(relist, 2, PyLong_FromLong(102));
//返回修改后参数
return relist;*/
//引用计数+1 ,?返回后会被-1
Py_XINCREF(lis1);
return lis1;
}
static PyObject *test_tuple(PyObject *self, PyObject*args)
{
//获取元组对象
PyObject *tup = NULL;
if (!PyArg_ParseTuple(args, "O", &tup))
{
return NULL;
}
//元组大小
Py_ssize_t size = PyTuple_Size(tup);
printf("\n=====================================\n");
for (int i = 0; i < size; i++)
{
//元组的元素
PyObject *val = PyTuple_GetItem(tup, i);
//二维元组
if (PyTuple_Check(val))
{
Py_ssize_t s = PyTuple_Size(val);
printf(" ( ");
for (int j = 0; j < s; j++)
{
PyObject *v = PyTuple_GetItem(val, j);
printf("%d ", PyLong_AsLong(v));
}
printf(" ) ");
continue;
}
int r = PyLong_AsLong(val);
printf("%d ", r);
}
//Py_RETURN_NONE;
//返回元组
PyObject *retup = PyTuple_New(10);
PyTuple_SetItem(retup, 0, PyLong_FromLong(102));
PyTuple_SetItem(retup, 1, PyUnicode_FromString("Test Tuple return string "));
//二级元组
PyObject *tup2 = PyTuple_New(3);
PyTuple_SetItem(tup2, 0, PyLong_FromLong(201));
PyTuple_SetItem(retup, 3, tup2);
return retup;
}
static PyObject *test_kw(PyObject *self, PyObject*args, PyObject*kw)
{
const char *name = "";
int age = 10;
int score = 60;
static char *keys[] = { "name","age","score",NULL };
if (!PyArg_ParseTupleAndKeywords(args,kw,"s|ii", keys,&name,&age,&score))
{
return NULL; //0 抛出异常
}
printf("Name is %s age is %d score is %d \n", name, age, score);
Py_RETURN_NONE; //None
}
static PyObject *test_string(PyObject *self, PyObject*args)
{
char *str = 0;
//str 会指向python内部空间
if (!PyArg_ParseTuple(args, "s", &str))
{
return NULL;
}
//传递过来的字符串是utf-8格式,控制台默认GBK,中文乱码
printf("PyArg_ParseTuple return string = %s \n", str);
//如果有中文,要把代码设置为utf-8格式
//分配空间,引用计数+1 ,交给python解释器释放
return PyUnicode_FromString("PyUnicode_FromString in c return ");
}
static PyObject *test_float(PyObject *self, PyObject*arg)
{
printf("test_float\n");
if (PyFloat_Check(arg))
{
double a = PyFloat_AsDouble(arg);
printf("arg type is float ,value = %f \n",a);
}
else
{
printf("arg type is not float\n");
}
return PyLong_FromLong(0);
}
///5 模块函数
static PyObject *testmod(PyObject *self,PyObject*args)
{
int x = 0;
int y = 0;
float z = 0.0;
//失败会写入异常信息
if (!PyArg_ParseTuple(args, "iif", &x,&y,&z))
{
printf("PyArg_ParseTuple");
return NULL; //会抛出异常
}
printf("PyArg_ParseTuple x = %d y = %d z = %f\n", x,y,z);
//返回python的long整形,c语言中引用计数+1,返回值交由python释放,
return PyLong_FromLong(105);
}
///4 模块函数列表
static PyMethodDef mymod_funcs[] = {
{
"testmod", //函数名称
testmod, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"testmod function." //函数说明 help(testmod)
},
{
"test_float", //函数名称
test_float, //函数指针
METH_O, // 只有一个参数,参数标识 无参数 METH_VARARGS METH_NOARGS METH_O
"test_float function." //函数说明 help(testmod)
},
{
"test_string", //函数名称
test_string, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"test_string function." //函数说明 help(testmod)
},
{
"test_kw", //函数名称
test_kw, //函数指针
METH_VARARGS| METH_KEYWORDS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_tuple", //函数名称
test_tuple, //函数指针
METH_VARARGS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_list", //函数名称
test_list, //函数指针
METH_VARARGS,//关键字参数
"test_list function." //函数说明 help(testmod)
},
{
"test_dict", //函数名称
test_dict, //函数指针
METH_VARARGS,//关键字参数
"test_dict function." //函数说明 help(testmod)
},
{0,0,0,0}
};
///3 模块定义
static PyModuleDef mymod_module = {
PyModuleDef_HEAD_INIT,
"TestPythonExt", //模块名
"TestPythonExt is first module test", //模块说明 通过help(模块名)
-1, //模块空间,子解释器用,-1不使用
mymod_funcs //模块函数
};
///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名
PyMODINIT_FUNC PyInit_TestPythonExt(void)
{
printf("PyInit_TestPythonExt\n");
///2 模块创建函数 参数 PyModuleDef
return PyModule_Create(&mymod_module);
}
setup.py
from distutils.core import *
setup(
name="TestPythonExt", #打包文件名称
version="1.0",
ext_modules=[Extension("TestPythonExt", ["mymod.c"] )]
)
testmod.py
print("Test TestPythonExt Module")
#import TestPythonExt
from TestPythonExt import *
#print(help(mymod))
try:
#print(TestPythonExt.testmod(999, 555,33.44))
print(testmod(999, 555,33.44))
test_float("xx")
test_float(66.)
a = test_string("Python string to C++")
print("test_string return type is ",type(a))
print("test_string return= \" ", a,"\"")
test_kw(name="xiaoming1",age=20,score=100)
test_kw(name="xiaoming2")
test_kw("xiaoming3",15,70)
test_kw("xiaoming4",score=150)
tup = (1,2,4,5,6,7,8,9,10,11)
test_tuple(tup)
tup2 = (1,2,4,5,6,7,8,9,10,11,(99,88,77,66,55))
test_tuple(tup2)
re = test_tuple(tup)
print("\n=============retur===============")
print(re)
print("=========test list===========")
try:
test_list(111)
except Exception as e:
print("List Exception",type(e),e)
list1 = [0,1,2,3,4,5,6,7,8,9,10]
print("\nIn Python begin:",list1)
re = test_list(list1)
print("\nIn Python end:",list1)
print(re)
print("list1 id",id(list1), " re id=",id(re))
#返回值会被引用计数-1
test_list(list1)
print(list1)
#测试内存消耗
while True:
dic = {"name":"xiaoming"}
test_dict(dic)
except Exception as e:
print("Exception",type(e),e)
input()
0-15扩展库函数参数遍历字典PyDict_Keys并清理相应空间
mymod.c
#include "Python.h"
static PyObject *test_dict(PyObject *self, PyObject*args)
{
PyObject *dic = NULL;
PyArg_ParseTuple(args, "O", &dic);
if (!PyDict_Check(dic))
{
//设置异常类型和信息,return NULL抛出异常
PyErr_SetString(PyExc_Exception, "arg must be dict");
return NULL;
}
//判断是否由此关键字
//申请空间 引用计数+1 不释放会内存泄漏
PyObject *key = PyUnicode_FromString("name");
int re = PyDict_Contains(dic, key);
Py_XDECREF(key);//引用计数-1 为0清理
if (!re) //无空间操作
{
PyErr_SetString(PyExc_Exception, "key name must be set");
return NULL;
}
//读取关键字的值
{
PyObject *key = PyUnicode_FromString("name");
PyObject *val = PyDict_GetItem(dic, key); //只做引用
//PyUnicode_AsUnicode(val) 3.3开始过时, 4.0丢弃 空间不明确
wchar_t buf[1024] = { 0 };
PyUnicode_AsWideChar(val, buf, sizeof(buf));
//wprintf("PyDict_GetItem = %s\n", PyUnicode_AsUnicode(val));
wprintf(L"PyDict_GetItem = %s\n", buf);
Py_XDECREF(key);//引用计数-1 为0清理
val = PyDict_GetItemString(dic, "name");
PyUnicode_AsWideChar(val, buf, sizeof(buf));
wprintf(L"PyDict_GetItemString = %s\n", buf);
}
{
//遍历key 和value
//返回所有的关键字PyList PyList类型,新增的空间
PyObject *keys = PyDict_Keys(dic);
PyObject *vals = PyDict_Values(dic);
int size = PyList_Size(keys);
wchar_t buf[1024] = { 0 };
printf("\n=================keys====================\n");
for (int i = 0; i < size; i++)
{
//取的Key
PyObject *key = PyList_GetItem(keys, i);
PyUnicode_AsWideChar(key, buf, sizeof(buf));
wprintf(L"{%s:", buf);
//取value
PyObject *val = PyList_GetItem(vals, i);
if (PyUnicode_Check(val))
{
PyUnicode_AsWideChar(val, buf, sizeof(buf));
wprintf(L"%s", buf);
}
else if (PyLong_Check(val))
{
wprintf(L"%d", PyLong_AsLong(val));
}
else
{
wprintf(L"unknown");
}
wprintf(L"}");
}
printf("\n=========================================\n");
//结对编程 空间申请和释放成对出现
Py_XDECREF(keys);
Py_XDECREF(vals);
}
return PyLong_FromLong(0);
}
static PyObject *test_list(PyObject *self, PyObject*args)
{
PyObject *lis1 = NULL;
if (!PyArg_ParseTuple(args, "O", &lis1))
{
return NULL;
}
if (!PyList_Check(lis1))
{
//异常信息
PyErr_SetString(PyExc_Exception, "arg must be list");
return NULL;
}
Py_ssize_t size = PyList_Size(lis1);
for (int i = 0; i < size; i++)
{
PyObject *val = PyList_GetItem(lis1, i);
int r = PyLong_AsLong(val);
printf("%d ", r);
}
printf("\n");
//修改参数list
//结尾处新增
PyList_Append(lis1, PyLong_FromLong(11));
//插入
PyList_Insert(lis1, 4, PyFloat_FromDouble(3.1));
//修改
PyList_SetItem(lis1, 2, PyLong_FromLong(20));
//删除 1开始位置 2结束位置之前
PyList_SetSlice(lis1, 1, 2, 0);
//返回一个新创建的列表 ,空间交给python释放
/*PyObject *relist = PyList_New(0);
PyList_Append(relist, PyLong_FromLong(100));
PyList_Append(relist, PyLong_FromLong(101));
PyList_Insert(relist, 2, PyLong_FromLong(102));
//返回修改后参数
return relist;*/
//引用计数+1 ,?返回后会被-1
Py_XINCREF(lis1);
return lis1;
}
static PyObject *test_tuple(PyObject *self, PyObject*args)
{
//获取元组对象
PyObject *tup = NULL;
if (!PyArg_ParseTuple(args, "O", &tup))
{
return NULL;
}
//元组大小
Py_ssize_t size = PyTuple_Size(tup);
printf("\n=====================================\n");
for (int i = 0; i < size; i++)
{
//元组的元素
PyObject *val = PyTuple_GetItem(tup, i);
//二维元组
if (PyTuple_Check(val))
{
Py_ssize_t s = PyTuple_Size(val);
printf(" ( ");
for (int j = 0; j < s; j++)
{
PyObject *v = PyTuple_GetItem(val, j);
printf("%d ", PyLong_AsLong(v));
}
printf(" ) ");
continue;
}
int r = PyLong_AsLong(val);
printf("%d ", r);
}
//Py_RETURN_NONE;
//返回元组
PyObject *retup = PyTuple_New(10);
PyTuple_SetItem(retup, 0, PyLong_FromLong(102));
PyTuple_SetItem(retup, 1, PyUnicode_FromString("Test Tuple return string "));
//二级元组
PyObject *tup2 = PyTuple_New(3);
PyTuple_SetItem(tup2, 0, PyLong_FromLong(201));
PyTuple_SetItem(retup, 3, tup2);
return retup;
}
static PyObject *test_kw(PyObject *self, PyObject*args, PyObject*kw)
{
const char *name = "";
int age = 10;
int score = 60;
static char *keys[] = { "name","age","score",NULL };
if (!PyArg_ParseTupleAndKeywords(args,kw,"s|ii", keys,&name,&age,&score))
{
return NULL; //0 抛出异常
}
printf("Name is %s age is %d score is %d \n", name, age, score);
Py_RETURN_NONE; //None
}
static PyObject *test_string(PyObject *self, PyObject*args)
{
char *str = 0;
//str 会指向python内部空间
if (!PyArg_ParseTuple(args, "s", &str))
{
return NULL;
}
//传递过来的字符串是utf-8格式,控制台默认GBK,中文乱码
printf("PyArg_ParseTuple return string = %s \n", str);
//如果有中文,要把代码设置为utf-8格式
//分配空间,引用计数+1 ,交给python解释器释放
return PyUnicode_FromString("PyUnicode_FromString in c return ");
}
static PyObject *test_float(PyObject *self, PyObject*arg)
{
printf("test_float\n");
if (PyFloat_Check(arg))
{
double a = PyFloat_AsDouble(arg);
printf("arg type is float ,value = %f \n",a);
}
else
{
printf("arg type is not float\n");
}
return PyLong_FromLong(0);
}
///5 模块函数
static PyObject *testmod(PyObject *self,PyObject*args)
{
int x = 0;
int y = 0;
float z = 0.0;
//失败会写入异常信息
if (!PyArg_ParseTuple(args, "iif", &x,&y,&z))
{
printf("PyArg_ParseTuple");
return NULL; //会抛出异常
}
printf("PyArg_ParseTuple x = %d y = %d z = %f\n", x,y,z);
//返回python的long整形,c语言中引用计数+1,返回值交由python释放,
return PyLong_FromLong(105);
}
///4 模块函数列表
static PyMethodDef mymod_funcs[] = {
{
"testmod", //函数名称
testmod, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"testmod function." //函数说明 help(testmod)
},
{
"test_float", //函数名称
test_float, //函数指针
METH_O, // 只有一个参数,参数标识 无参数 METH_VARARGS METH_NOARGS METH_O
"test_float function." //函数说明 help(testmod)
},
{
"test_string", //函数名称
test_string, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"test_string function." //函数说明 help(testmod)
},
{
"test_kw", //函数名称
test_kw, //函数指针
METH_VARARGS| METH_KEYWORDS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_tuple", //函数名称
test_tuple, //函数指针
METH_VARARGS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_list", //函数名称
test_list, //函数指针
METH_VARARGS,//关键字参数
"test_list function." //函数说明 help(testmod)
},
{
"test_dict", //函数名称
test_dict, //函数指针
METH_VARARGS,//关键字参数
"test_dict function." //函数说明 help(testmod)
},
{0,0,0,0}
};
///3 模块定义
static PyModuleDef mymod_module = {
PyModuleDef_HEAD_INIT,
"TestPythonExt", //模块名
"TestPythonExt is first module test", //模块说明 通过help(模块名)
-1, //模块空间,子解释器用,-1不使用
mymod_funcs //模块函数
};
///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名
PyMODINIT_FUNC PyInit_TestPythonExt(void)
{
printf("PyInit_TestPythonExt\n");
///2 模块创建函数 参数 PyModuleDef
return PyModule_Create(&mymod_module);
}
setup.py
from distutils.core import *
setup(
name="TestPythonExt", #打包文件名称
version="1.0",
ext_modules=[Extension("TestPythonExt", ["mymod.c"] )]
)
testmod.py
print("Test TestPythonExt Module")
#import TestPythonExt
from TestPythonExt import *
#print(help(mymod))
try:
#print(TestPythonExt.testmod(999, 555,33.44))
print(testmod(999, 555,33.44))
test_float("xx")
test_float(66.)
a = test_string("Python string to C++")
print("test_string return type is ",type(a))
print("test_string return= \" ", a,"\"")
test_kw(name="xiaoming1",age=20,score=100)
test_kw(name="xiaoming2")
test_kw("xiaoming3",15,70)
test_kw("xiaoming4",score=150)
tup = (1,2,4,5,6,7,8,9,10,11)
test_tuple(tup)
tup2 = (1,2,4,5,6,7,8,9,10,11,(99,88,77,66,55))
test_tuple(tup2)
re = test_tuple(tup)
print("\n=============retur===============")
print(re)
print("=========test list===========")
try:
test_list(111)
except Exception as e:
print("List Exception",type(e),e)
list1 = [0,1,2,3,4,5,6,7,8,9,10]
print("\nIn Python begin:",list1)
re = test_list(list1)
print("\nIn Python end:",list1)
print(re)
print("list1 id",id(list1), " re id=",id(re))
#返回值会被引用计数-1
test_list(list1)
print(list1)
#测试内存消耗
#while True:
dic = {"name":"xiaoming","age":20,"score":100,"title":"dic title"}
test_dict(dic)
except Exception as e:
print("Exception",type(e),e)
input()
0-16扩展库PyDict_Next迭代访问字典内容并封装PyObject打印函数
mymod.c
#include "Python.h"
void PrintObject(PyObject *obj)
{
wchar_t buf[1024] = { 0 };
if (PyUnicode_Check(obj))
{
PyUnicode_AsWideChar(obj, buf, sizeof(buf));
wprintf(L"%s", buf);
}
else if (PyLong_Check(obj))
{
wprintf(L"%d", PyLong_AsLong(obj));
}
else
{
wprintf(L"unknown");
}
}
static PyObject *test_dict(PyObject *self, PyObject*args)
{
PyObject *dic = NULL;
PyArg_ParseTuple(args, "O", &dic);
if (!PyDict_Check(dic))
{
//设置异常类型和信息,return NULL抛出异常
PyErr_SetString(PyExc_Exception, "arg must be dict");
return NULL;
}
//判断是否由此关键字
//申请空间 引用计数+1 不释放会内存泄漏
PyObject *key = PyUnicode_FromString("name");
int re = PyDict_Contains(dic, key);
Py_XDECREF(key);//引用计数-1 为0清理
if (!re) //无空间操作
{
PyErr_SetString(PyExc_Exception, "key name must be set");
return NULL;
}
//读取关键字的值
{
PyObject *key = PyUnicode_FromString("name");
PyObject *val = PyDict_GetItem(dic, key); //只做引用
//PyUnicode_AsUnicode(val) 3.3开始过时, 4.0丢弃 空间不明确
wchar_t buf[1024] = { 0 };
PyUnicode_AsWideChar(val, buf, sizeof(buf));
//wprintf("PyDict_GetItem = %s\n", PyUnicode_AsUnicode(val));
wprintf(L"PyDict_GetItem = %s\n", buf);
Py_XDECREF(key);//引用计数-1 为0清理
val = PyDict_GetItemString(dic, "name");
PyUnicode_AsWideChar(val, buf, sizeof(buf));
wprintf(L"PyDict_GetItemString = %s\n", buf);
}
{
//遍历key 和value
//返回所有的关键字PyList PyList类型,新增的空间
PyObject *keys = PyDict_Keys(dic);
PyObject *vals = PyDict_Values(dic);
int size = PyList_Size(keys);
wchar_t buf[1024] = { 0 };
printf("\n=================keys====================\n");
for (int i = 0; i < size; i++)
{
//取的Key
PyObject *key = PyList_GetItem(keys, i);
PyUnicode_AsWideChar(key, buf, sizeof(buf));
wprintf(L"{%s:", buf);
//取value
PyObject *val = PyList_GetItem(vals, i);
if (PyUnicode_Check(val))
{
PyUnicode_AsWideChar(val, buf, sizeof(buf));
wprintf(L"%s", buf);
}
else if (PyLong_Check(val))
{
wprintf(L"%d", PyLong_AsLong(val));
}
else
{
wprintf(L"unknown");
}
wprintf(L"}");
}
printf("\n=========================================\n");
//结对编程 空间申请和释放成对出现
Py_XDECREF(keys);
Py_XDECREF(vals);
}
{
//迭代器来遍历dict
PyObject *key = 0;
PyObject *value = 0;
Py_ssize_t pos = 0;
printf("PyDict_Next{");
while (PyDict_Next(dic, &pos, &key, &value))
{
PrintObject(key);
printf(":");
PrintObject(value);
printf(",");
}
printf("}");
}
return PyLong_FromLong(0);
}
static PyObject *test_list(PyObject *self, PyObject*args)
{
PyObject *lis1 = NULL;
if (!PyArg_ParseTuple(args, "O", &lis1))
{
return NULL;
}
if (!PyList_Check(lis1))
{
//异常信息
PyErr_SetString(PyExc_Exception, "arg must be list");
return NULL;
}
Py_ssize_t size = PyList_Size(lis1);
for (int i = 0; i < size; i++)
{
PyObject *val = PyList_GetItem(lis1, i);
int r = PyLong_AsLong(val);
printf("%d ", r);
}
printf("\n");
//修改参数list
//结尾处新增
PyList_Append(lis1, PyLong_FromLong(11));
//插入
PyList_Insert(lis1, 4, PyFloat_FromDouble(3.1));
//修改
PyList_SetItem(lis1, 2, PyLong_FromLong(20));
//删除 1开始位置 2结束位置之前
PyList_SetSlice(lis1, 1, 2, 0);
//返回一个新创建的列表 ,空间交给python释放
/*PyObject *relist = PyList_New(0);
PyList_Append(relist, PyLong_FromLong(100));
PyList_Append(relist, PyLong_FromLong(101));
PyList_Insert(relist, 2, PyLong_FromLong(102));
//返回修改后参数
return relist;*/
//引用计数+1 ,?返回后会被-1
Py_XINCREF(lis1);
return lis1;
}
static PyObject *test_tuple(PyObject *self, PyObject*args)
{
//获取元组对象
PyObject *tup = NULL;
if (!PyArg_ParseTuple(args, "O", &tup))
{
return NULL;
}
//元组大小
Py_ssize_t size = PyTuple_Size(tup);
printf("\n=====================================\n");
for (int i = 0; i < size; i++)
{
//元组的元素
PyObject *val = PyTuple_GetItem(tup, i);
//二维元组
if (PyTuple_Check(val))
{
Py_ssize_t s = PyTuple_Size(val);
printf(" ( ");
for (int j = 0; j < s; j++)
{
PyObject *v = PyTuple_GetItem(val, j);
printf("%d ", PyLong_AsLong(v));
}
printf(" ) ");
continue;
}
int r = PyLong_AsLong(val);
printf("%d ", r);
}
//Py_RETURN_NONE;
//返回元组
PyObject *retup = PyTuple_New(10);
PyTuple_SetItem(retup, 0, PyLong_FromLong(102));
PyTuple_SetItem(retup, 1, PyUnicode_FromString("Test Tuple return string "));
//二级元组
PyObject *tup2 = PyTuple_New(3);
PyTuple_SetItem(tup2, 0, PyLong_FromLong(201));
PyTuple_SetItem(retup, 3, tup2);
return retup;
}
static PyObject *test_kw(PyObject *self, PyObject*args, PyObject*kw)
{
const char *name = "";
int age = 10;
int score = 60;
static char *keys[] = { "name","age","score",NULL };
if (!PyArg_ParseTupleAndKeywords(args,kw,"s|ii", keys,&name,&age,&score))
{
return NULL; //0 抛出异常
}
printf("Name is %s age is %d score is %d \n", name, age, score);
Py_RETURN_NONE; //None
}
static PyObject *test_string(PyObject *self, PyObject*args)
{
char *str = 0;
//str 会指向python内部空间
if (!PyArg_ParseTuple(args, "s", &str))
{
return NULL;
}
//传递过来的字符串是utf-8格式,控制台默认GBK,中文乱码
printf("PyArg_ParseTuple return string = %s \n", str);
//如果有中文,要把代码设置为utf-8格式
//分配空间,引用计数+1 ,交给python解释器释放
return PyUnicode_FromString("PyUnicode_FromString in c return ");
}
static PyObject *test_float(PyObject *self, PyObject*arg)
{
printf("test_float\n");
if (PyFloat_Check(arg))
{
double a = PyFloat_AsDouble(arg);
printf("arg type is float ,value = %f \n",a);
}
else
{
printf("arg type is not float\n");
}
return PyLong_FromLong(0);
}
///5 模块函数
static PyObject *testmod(PyObject *self,PyObject*args)
{
int x = 0;
int y = 0;
float z = 0.0;
//失败会写入异常信息
if (!PyArg_ParseTuple(args, "iif", &x,&y,&z))
{
printf("PyArg_ParseTuple");
return NULL; //会抛出异常
}
printf("PyArg_ParseTuple x = %d y = %d z = %f\n", x,y,z);
//返回python的long整形,c语言中引用计数+1,返回值交由python释放,
return PyLong_FromLong(105);
}
///4 模块函数列表
static PyMethodDef mymod_funcs[] = {
{
"testmod", //函数名称
testmod, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"testmod function." //函数说明 help(testmod)
},
{
"test_float", //函数名称
test_float, //函数指针
METH_O, // 只有一个参数,参数标识 无参数 METH_VARARGS METH_NOARGS METH_O
"test_float function." //函数说明 help(testmod)
},
{
"test_string", //函数名称
test_string, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"test_string function." //函数说明 help(testmod)
},
{
"test_kw", //函数名称
test_kw, //函数指针
METH_VARARGS| METH_KEYWORDS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_tuple", //函数名称
test_tuple, //函数指针
METH_VARARGS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_list", //函数名称
test_list, //函数指针
METH_VARARGS,//关键字参数
"test_list function." //函数说明 help(testmod)
},
{
"test_dict", //函数名称
test_dict, //函数指针
METH_VARARGS,//关键字参数
"test_dict function." //函数说明 help(testmod)
},
{0,0,0,0}
};
///3 模块定义
static PyModuleDef mymod_module = {
PyModuleDef_HEAD_INIT,
"TestPythonExt", //模块名
"TestPythonExt is first module test", //模块说明 通过help(模块名)
-1, //模块空间,子解释器用,-1不使用
mymod_funcs //模块函数
};
///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名
PyMODINIT_FUNC PyInit_TestPythonExt(void)
{
printf("PyInit_TestPythonExt\n");
///2 模块创建函数 参数 PyModuleDef
return PyModule_Create(&mymod_module);
}
setup.py
from distutils.core import *
setup(
name="TestPythonExt", #打包文件名称
version="1.0",
ext_modules=[Extension("TestPythonExt", ["mymod.c"] )]
)
testmod.py
print("Test TestPythonExt Module")
#import TestPythonExt
from TestPythonExt import *
#print(help(mymod))
try:
#print(TestPythonExt.testmod(999, 555,33.44))
print(testmod(999, 555,33.44))
test_float("xx")
test_float(66.)
a = test_string("Python string to C++")
print("test_string return type is ",type(a))
print("test_string return= \" ", a,"\"")
test_kw(name="xiaoming1",age=20,score=100)
test_kw(name="xiaoming2")
test_kw("xiaoming3",15,70)
test_kw("xiaoming4",score=150)
tup = (1,2,4,5,6,7,8,9,10,11)
test_tuple(tup)
tup2 = (1,2,4,5,6,7,8,9,10,11,(99,88,77,66,55))
test_tuple(tup2)
re = test_tuple(tup)
print("\n=============retur===============")
print(re)
print("=========test list===========")
try:
test_list(111)
except Exception as e:
print("List Exception",type(e),e)
list1 = [0,1,2,3,4,5,6,7,8,9,10]
print("\nIn Python begin:",list1)
re = test_list(list1)
print("\nIn Python end:",list1)
print(re)
print("list1 id",id(list1), " re id=",id(re))
#返回值会被引用计数-1
test_list(list1)
print(list1)
#测试内存消耗
#while True:
dic = {"name":"xiaoming","age":20,"score":100,"title":"dic title"}
test_dict(dic)
except Exception as e:
print("Exception",type(e),e)
input()
0-17扩展库处理dict参数插入修改和删除数据
mymod.c
#include "Python.h"
void SetDictString(PyObject *dic, const char *key, const char *val)
{
PyObject *k = PyUnicode_FromString(key); //引用计数+1
PyObject *v = PyUnicode_FromString(val); //引用计数+1
PyDict_SetItem(dic, k, v); //会将k 和v 引用计数+1
Py_XDECREF(k);
Py_XDECREF(v);
}
void PrintObject(PyObject *obj)
{
wchar_t buf[1024] = { 0 };
if (PyUnicode_Check(obj))
{
PyUnicode_AsWideChar(obj, buf, sizeof(buf));
wprintf(L"%s", buf);
}
else if (PyLong_Check(obj))
{
wprintf(L"%d", PyLong_AsLong(obj));
}
else
{
wprintf(L"unknown");
}
}
static PyObject *test_dict(PyObject *self, PyObject*args)
{
PyObject *dic = NULL;
PyArg_ParseTuple(args, "O", &dic);
if (!PyDict_Check(dic))
{
//设置异常类型和信息,return NULL抛出异常
PyErr_SetString(PyExc_Exception, "arg must be dict");
return NULL;
}
//判断是否由此关键字
//申请空间 引用计数+1 不释放会内存泄漏
PyObject *key = PyUnicode_FromString("name");
int re = PyDict_Contains(dic, key);
Py_XDECREF(key);//引用计数-1 为0清理
if (!re) //无空间操作
{
PyErr_SetString(PyExc_Exception, "key name must be set");
return NULL;
}
//读取关键字的值
{
PyObject *key = PyUnicode_FromString("name");
PyObject *val = PyDict_GetItem(dic, key); //只做引用
//PyUnicode_AsUnicode(val) 3.3开始过时, 4.0丢弃 空间不明确
wchar_t buf[1024] = { 0 };
PyUnicode_AsWideChar(val, buf, sizeof(buf));
//wprintf("PyDict_GetItem = %s\n", PyUnicode_AsUnicode(val));
wprintf(L"PyDict_GetItem = %s\n", buf);
Py_XDECREF(key);//引用计数-1 为0清理
val = PyDict_GetItemString(dic, "name");
PyUnicode_AsWideChar(val, buf, sizeof(buf));
wprintf(L"PyDict_GetItemString = %s\n", buf);
}
{
//遍历key 和value
//返回所有的关键字PyList PyList类型,新增的空间
PyObject *keys = PyDict_Keys(dic);
PyObject *vals = PyDict_Values(dic);
int size = PyList_Size(keys);
wchar_t buf[1024] = { 0 };
printf("\n=================keys====================\n");
for (int i = 0; i < size; i++)
{
//取的Key
PyObject *key = PyList_GetItem(keys, i);
PyUnicode_AsWideChar(key, buf, sizeof(buf));
wprintf(L"{%s:", buf);
//取value
PyObject *val = PyList_GetItem(vals, i);
if (PyUnicode_Check(val))
{
PyUnicode_AsWideChar(val, buf, sizeof(buf));
wprintf(L"%s", buf);
}
else if (PyLong_Check(val))
{
wprintf(L"%d", PyLong_AsLong(val));
}
else
{
wprintf(L"unknown");
}
wprintf(L"}");
}
printf("\n=========================================\n");
//结对编程 空间申请和释放成对出现
Py_XDECREF(keys);
Py_XDECREF(vals);
}
{
//迭代器来遍历dict
PyObject *key = 0;
PyObject *value = 0;
Py_ssize_t pos = 0;
printf("PyDict_Next{");
while (PyDict_Next(dic, &pos, &key, &value))
{
PrintObject(key);
printf(":");
PrintObject(value);
printf(",");
}
printf("}");
}
//新增修改字典
{
PyObject *k = PyUnicode_FromString("title"); //引用计数+1
PyObject *v = PyUnicode_FromString("change title"); //引用计数+1
PyDict_SetItem(dic, k, v); //会将k 和v 引用计数+1
Py_XDECREF(k);
Py_XDECREF(v);
SetDictString(dic,"path", "C:\\img");
}
//删除字典
{
PyObject *k = PyUnicode_FromString("delkey");
if(PyDict_Contains(dic,k))
PyDict_DelItem(dic, k);
Py_XDECREF(k);
}
return PyLong_FromLong(0);
}
static PyObject *test_list(PyObject *self, PyObject*args)
{
PyObject *lis1 = NULL;
if (!PyArg_ParseTuple(args, "O", &lis1))
{
return NULL;
}
if (!PyList_Check(lis1))
{
//异常信息
PyErr_SetString(PyExc_Exception, "arg must be list");
return NULL;
}
Py_ssize_t size = PyList_Size(lis1);
for (int i = 0; i < size; i++)
{
PyObject *val = PyList_GetItem(lis1, i);
int r = PyLong_AsLong(val);
printf("%d ", r);
}
printf("\n");
//修改参数list
//结尾处新增
PyList_Append(lis1, PyLong_FromLong(11));
//插入
PyList_Insert(lis1, 4, PyFloat_FromDouble(3.1));
//修改
PyList_SetItem(lis1, 2, PyLong_FromLong(20));
//删除 1开始位置 2结束位置之前
PyList_SetSlice(lis1, 1, 2, 0);
//返回一个新创建的列表 ,空间交给python释放
/*PyObject *relist = PyList_New(0);
PyList_Append(relist, PyLong_FromLong(100));
PyList_Append(relist, PyLong_FromLong(101));
PyList_Insert(relist, 2, PyLong_FromLong(102));
//返回修改后参数
return relist;*/
//引用计数+1 ,?返回后会被-1
Py_XINCREF(lis1);
return lis1;
}
static PyObject *test_tuple(PyObject *self, PyObject*args)
{
//获取元组对象
PyObject *tup = NULL;
if (!PyArg_ParseTuple(args, "O", &tup))
{
return NULL;
}
//元组大小
Py_ssize_t size = PyTuple_Size(tup);
printf("\n=====================================\n");
for (int i = 0; i < size; i++)
{
//元组的元素
PyObject *val = PyTuple_GetItem(tup, i);
//二维元组
if (PyTuple_Check(val))
{
Py_ssize_t s = PyTuple_Size(val);
printf(" ( ");
for (int j = 0; j < s; j++)
{
PyObject *v = PyTuple_GetItem(val, j);
printf("%d ", PyLong_AsLong(v));
}
printf(" ) ");
continue;
}
int r = PyLong_AsLong(val);
printf("%d ", r);
}
//Py_RETURN_NONE;
//返回元组
PyObject *retup = PyTuple_New(10);
PyTuple_SetItem(retup, 0, PyLong_FromLong(102));
PyTuple_SetItem(retup, 1, PyUnicode_FromString("Test Tuple return string "));
//二级元组
PyObject *tup2 = PyTuple_New(3);
PyTuple_SetItem(tup2, 0, PyLong_FromLong(201));
PyTuple_SetItem(retup, 3, tup2);
return retup;
}
static PyObject *test_kw(PyObject *self, PyObject*args, PyObject*kw)
{
const char *name = "";
int age = 10;
int score = 60;
static char *keys[] = { "name","age","score",NULL };
if (!PyArg_ParseTupleAndKeywords(args,kw,"s|ii", keys,&name,&age,&score))
{
return NULL; //0 抛出异常
}
printf("Name is %s age is %d score is %d \n", name, age, score);
Py_RETURN_NONE; //None
}
static PyObject *test_string(PyObject *self, PyObject*args)
{
char *str = 0;
//str 会指向python内部空间
if (!PyArg_ParseTuple(args, "s", &str))
{
return NULL;
}
//传递过来的字符串是utf-8格式,控制台默认GBK,中文乱码
printf("PyArg_ParseTuple return string = %s \n", str);
//如果有中文,要把代码设置为utf-8格式
//分配空间,引用计数+1 ,交给python解释器释放
return PyUnicode_FromString("PyUnicode_FromString in c return ");
}
static PyObject *test_float(PyObject *self, PyObject*arg)
{
printf("test_float\n");
if (PyFloat_Check(arg))
{
double a = PyFloat_AsDouble(arg);
printf("arg type is float ,value = %f \n",a);
}
else
{
printf("arg type is not float\n");
}
return PyLong_FromLong(0);
}
///5 模块函数
static PyObject *testmod(PyObject *self,PyObject*args)
{
int x = 0;
int y = 0;
float z = 0.0;
//失败会写入异常信息
if (!PyArg_ParseTuple(args, "iif", &x,&y,&z))
{
printf("PyArg_ParseTuple");
return NULL; //会抛出异常
}
printf("PyArg_ParseTuple x = %d y = %d z = %f\n", x,y,z);
//返回python的long整形,c语言中引用计数+1,返回值交由python释放,
return PyLong_FromLong(105);
}
///4 模块函数列表
static PyMethodDef mymod_funcs[] = {
{
"testmod", //函数名称
testmod, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"testmod function." //函数说明 help(testmod)
},
{
"test_float", //函数名称
test_float, //函数指针
METH_O, // 只有一个参数,参数标识 无参数 METH_VARARGS METH_NOARGS METH_O
"test_float function." //函数说明 help(testmod)
},
{
"test_string", //函数名称
test_string, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"test_string function." //函数说明 help(testmod)
},
{
"test_kw", //函数名称
test_kw, //函数指针
METH_VARARGS| METH_KEYWORDS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_tuple", //函数名称
test_tuple, //函数指针
METH_VARARGS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_list", //函数名称
test_list, //函数指针
METH_VARARGS,//关键字参数
"test_list function." //函数说明 help(testmod)
},
{
"test_dict", //函数名称
test_dict, //函数指针
METH_VARARGS,//关键字参数
"test_dict function." //函数说明 help(testmod)
},
{0,0,0,0}
};
///3 模块定义
static PyModuleDef mymod_module = {
PyModuleDef_HEAD_INIT,
"TestPythonExt", //模块名
"TestPythonExt is first module test", //模块说明 通过help(模块名)
-1, //模块空间,子解释器用,-1不使用
mymod_funcs //模块函数
};
///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名
PyMODINIT_FUNC PyInit_TestPythonExt(void)
{
printf("PyInit_TestPythonExt\n");
///2 模块创建函数 参数 PyModuleDef
return PyModule_Create(&mymod_module);
}
setup.py
from distutils.core import *
setup(
name="TestPythonExt", #打包文件名称
version="1.0",
ext_modules=[Extension("TestPythonExt", ["mymod.c"] )]
)
testmod.py
print("Test TestPythonExt Module")
#import TestPythonExt
from TestPythonExt import *
#print(help(mymod))
try:
#print(TestPythonExt.testmod(999, 555,33.44))
print(testmod(999, 555,33.44))
test_float("xx")
test_float(66.)
a = test_string("Python string to C++")
print("test_string return type is ",type(a))
print("test_string return= \" ", a,"\"")
test_kw(name="xiaoming1",age=20,score=100)
test_kw(name="xiaoming2")
test_kw("xiaoming3",15,70)
test_kw("xiaoming4",score=150)
tup = (1,2,4,5,6,7,8,9,10,11)
test_tuple(tup)
tup2 = (1,2,4,5,6,7,8,9,10,11,(99,88,77,66,55))
test_tuple(tup2)
re = test_tuple(tup)
print("\n=============retur===============")
print(re)
print("=========test list===========")
try:
test_list(111)
except Exception as e:
print("List Exception",type(e),e)
list1 = [0,1,2,3,4,5,6,7,8,9,10]
print("\nIn Python begin:",list1)
re = test_list(list1)
print("\nIn Python end:",list1)
print(re)
print("list1 id",id(list1), " re id=",id(re))
#返回值会被引用计数-1
test_list(list1)
print(list1)
#测试内存消耗
#while True:
dic = {"name":"xiaoming","age":20,"score":100,"title":"dic title","delkey":"delstring"}
print(dic)
test_dict(dic)
print("\n==========changed========")
print(dic)
except Exception as e:
print("Exception",type(e),e)
input()
0-18扩展库函数返回dictionary字段
mymod.c
#include "Python.h"
void SetDictLong(PyObject *dic, const char *key, long val)
{
PyObject *k = PyUnicode_FromString(key); //引用计数+1
PyObject *v = PyLong_FromLong(val); //引用计数+1
PyDict_SetItem(dic, k, v); //会将k 和v 引用计数+1
Py_XDECREF(k);
Py_XDECREF(v);
}
void SetDictString(PyObject *dic, const char *key, const char *val)
{
PyObject *k = PyUnicode_FromString(key); //引用计数+1
PyObject *v = PyUnicode_FromString(val); //引用计数+1
PyDict_SetItem(dic, k, v); //会将k 和v 引用计数+1
Py_XDECREF(k);
Py_XDECREF(v);
}
void PrintObject(PyObject *obj)
{
wchar_t buf[1024] = { 0 };
if (PyUnicode_Check(obj))
{
PyUnicode_AsWideChar(obj, buf, sizeof(buf));
wprintf(L"%s", buf);
}
else if (PyLong_Check(obj))
{
wprintf(L"%d", PyLong_AsLong(obj));
}
else
{
wprintf(L"unknown");
}
}
static PyObject *test_dict(PyObject *self, PyObject*args)
{
PyObject *dic = NULL;
PyArg_ParseTuple(args, "O", &dic);
if (!PyDict_Check(dic))
{
//设置异常类型和信息,return NULL抛出异常
PyErr_SetString(PyExc_Exception, "arg must be dict");
return NULL;
}
//判断是否由此关键字
//申请空间 引用计数+1 不释放会内存泄漏
PyObject *key = PyUnicode_FromString("name");
int re = PyDict_Contains(dic, key);
Py_XDECREF(key);//引用计数-1 为0清理
if (!re) //无空间操作
{
PyErr_SetString(PyExc_Exception, "key name must be set");
return NULL;
}
//读取关键字的值
{
PyObject *key = PyUnicode_FromString("name");
PyObject *val = PyDict_GetItem(dic, key); //只做引用
//PyUnicode_AsUnicode(val) 3.3开始过时, 4.0丢弃 空间不明确
wchar_t buf[1024] = { 0 };
PyUnicode_AsWideChar(val, buf, sizeof(buf));
//wprintf("PyDict_GetItem = %s\n", PyUnicode_AsUnicode(val));
wprintf(L"PyDict_GetItem = %s\n", buf);
Py_XDECREF(key);//引用计数-1 为0清理
val = PyDict_GetItemString(dic, "name");
PyUnicode_AsWideChar(val, buf, sizeof(buf));
wprintf(L"PyDict_GetItemString = %s\n", buf);
}
{
//遍历key 和value
//返回所有的关键字PyList PyList类型,新增的空间
PyObject *keys = PyDict_Keys(dic);
PyObject *vals = PyDict_Values(dic);
int size = PyList_Size(keys);
wchar_t buf[1024] = { 0 };
printf("\n=================keys====================\n");
for (int i = 0; i < size; i++)
{
//取的Key
PyObject *key = PyList_GetItem(keys, i);
PyUnicode_AsWideChar(key, buf, sizeof(buf));
wprintf(L"{%s:", buf);
//取value
PyObject *val = PyList_GetItem(vals, i);
if (PyUnicode_Check(val))
{
PyUnicode_AsWideChar(val, buf, sizeof(buf));
wprintf(L"%s", buf);
}
else if (PyLong_Check(val))
{
wprintf(L"%d", PyLong_AsLong(val));
}
else
{
wprintf(L"unknown");
}
wprintf(L"}");
}
printf("\n=========================================\n");
//结对编程 空间申请和释放成对出现
Py_XDECREF(keys);
Py_XDECREF(vals);
}
{
//迭代器来遍历dict
PyObject *key = 0;
PyObject *value = 0;
Py_ssize_t pos = 0;
printf("PyDict_Next{");
while (PyDict_Next(dic, &pos, &key, &value))
{
PrintObject(key);
printf(":");
PrintObject(value);
printf(",");
}
printf("}");
}
//新增修改字典
{
PyObject *k = PyUnicode_FromString("title"); //引用计数+1
PyObject *v = PyUnicode_FromString("change title"); //引用计数+1
PyDict_SetItem(dic, k, v); //会将k 和v 引用计数+1
Py_XDECREF(k);
Py_XDECREF(v);
SetDictString(dic,"path", "C:\\img");
}
//删除字典
{
PyObject *k = PyUnicode_FromString("delkey");
if(PyDict_Contains(dic,k))
PyDict_DelItem(dic, k);
Py_XDECREF(k);
}
//返回字段
PyObject *redic = PyDict_New();
SetDictString(redic, "doc", "doc txt");
SetDictLong(redic, "fps", 25);
SetDictLong(redic, "ms", 1000);
return redic;
//return PyLong_FromLong(0);
}
static PyObject *test_list(PyObject *self, PyObject*args)
{
PyObject *lis1 = NULL;
if (!PyArg_ParseTuple(args, "O", &lis1))
{
return NULL;
}
if (!PyList_Check(lis1))
{
//异常信息
PyErr_SetString(PyExc_Exception, "arg must be list");
return NULL;
}
Py_ssize_t size = PyList_Size(lis1);
for (int i = 0; i < size; i++)
{
PyObject *val = PyList_GetItem(lis1, i);
int r = PyLong_AsLong(val);
printf("%d ", r);
}
printf("\n");
//修改参数list
//结尾处新增
PyList_Append(lis1, PyLong_FromLong(11));
//插入
PyList_Insert(lis1, 4, PyFloat_FromDouble(3.1));
//修改
PyList_SetItem(lis1, 2, PyLong_FromLong(20));
//删除 1开始位置 2结束位置之前
PyList_SetSlice(lis1, 1, 2, 0);
//返回一个新创建的列表 ,空间交给python释放
/*PyObject *relist = PyList_New(0);
PyList_Append(relist, PyLong_FromLong(100));
PyList_Append(relist, PyLong_FromLong(101));
PyList_Insert(relist, 2, PyLong_FromLong(102));
//返回修改后参数
return relist;*/
//引用计数+1 ,?返回后会被-1
Py_XINCREF(lis1);
return lis1;
}
static PyObject *test_tuple(PyObject *self, PyObject*args)
{
//获取元组对象
PyObject *tup = NULL;
if (!PyArg_ParseTuple(args, "O", &tup))
{
return NULL;
}
//元组大小
Py_ssize_t size = PyTuple_Size(tup);
printf("\n=====================================\n");
for (int i = 0; i < size; i++)
{
//元组的元素
PyObject *val = PyTuple_GetItem(tup, i);
//二维元组
if (PyTuple_Check(val))
{
Py_ssize_t s = PyTuple_Size(val);
printf(" ( ");
for (int j = 0; j < s; j++)
{
PyObject *v = PyTuple_GetItem(val, j);
printf("%d ", PyLong_AsLong(v));
}
printf(" ) ");
continue;
}
int r = PyLong_AsLong(val);
printf("%d ", r);
}
//Py_RETURN_NONE;
//返回元组
PyObject *retup = PyTuple_New(10);
PyTuple_SetItem(retup, 0, PyLong_FromLong(102));
PyTuple_SetItem(retup, 1, PyUnicode_FromString("Test Tuple return string "));
//二级元组
PyObject *tup2 = PyTuple_New(3);
PyTuple_SetItem(tup2, 0, PyLong_FromLong(201));
PyTuple_SetItem(retup, 3, tup2);
return retup;
}
static PyObject *test_kw(PyObject *self, PyObject*args, PyObject*kw)
{
const char *name = "";
int age = 10;
int score = 60;
static char *keys[] = { "name","age","score",NULL };
if (!PyArg_ParseTupleAndKeywords(args,kw,"s|ii", keys,&name,&age,&score))
{
return NULL; //0 抛出异常
}
printf("Name is %s age is %d score is %d \n", name, age, score);
Py_RETURN_NONE; //None
}
static PyObject *test_string(PyObject *self, PyObject*args)
{
char *str = 0;
//str 会指向python内部空间
if (!PyArg_ParseTuple(args, "s", &str))
{
return NULL;
}
//传递过来的字符串是utf-8格式,控制台默认GBK,中文乱码
printf("PyArg_ParseTuple return string = %s \n", str);
//如果有中文,要把代码设置为utf-8格式
//分配空间,引用计数+1 ,交给python解释器释放
return PyUnicode_FromString("PyUnicode_FromString in c return ");
}
static PyObject *test_float(PyObject *self, PyObject*arg)
{
printf("test_float\n");
if (PyFloat_Check(arg))
{
double a = PyFloat_AsDouble(arg);
printf("arg type is float ,value = %f \n",a);
}
else
{
printf("arg type is not float\n");
}
return PyLong_FromLong(0);
}
///5 模块函数
static PyObject *testmod(PyObject *self,PyObject*args)
{
int x = 0;
int y = 0;
float z = 0.0;
//失败会写入异常信息
if (!PyArg_ParseTuple(args, "iif", &x,&y,&z))
{
printf("PyArg_ParseTuple");
return NULL; //会抛出异常
}
printf("PyArg_ParseTuple x = %d y = %d z = %f\n", x,y,z);
//返回python的long整形,c语言中引用计数+1,返回值交由python释放,
return PyLong_FromLong(105);
}
///4 模块函数列表
static PyMethodDef mymod_funcs[] = {
{
"testmod", //函数名称
testmod, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"testmod function." //函数说明 help(testmod)
},
{
"test_float", //函数名称
test_float, //函数指针
METH_O, // 只有一个参数,参数标识 无参数 METH_VARARGS METH_NOARGS METH_O
"test_float function." //函数说明 help(testmod)
},
{
"test_string", //函数名称
test_string, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"test_string function." //函数说明 help(testmod)
},
{
"test_kw", //函数名称
test_kw, //函数指针
METH_VARARGS| METH_KEYWORDS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_tuple", //函数名称
test_tuple, //函数指针
METH_VARARGS,//关键字参数
"test_kw function." //函数说明 help(testmod)
},
{
"test_list", //函数名称
test_list, //函数指针
METH_VARARGS,//关键字参数
"test_list function." //函数说明 help(testmod)
},
{
"test_dict", //函数名称
test_dict, //函数指针
METH_VARARGS,//关键字参数
"test_dict function." //函数说明 help(testmod)
},
{0,0,0,0}
};
///3 模块定义
static PyModuleDef mymod_module = {
PyModuleDef_HEAD_INIT,
"TestPythonExt", //模块名
"TestPythonExt is first module test", //模块说明 通过help(模块名)
-1, //模块空间,子解释器用,-1不使用
mymod_funcs //模块函数
};
///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名
PyMODINIT_FUNC PyInit_TestPythonExt(void)
{
printf("PyInit_TestPythonExt\n");
///2 模块创建函数 参数 PyModuleDef
return PyModule_Create(&mymod_module);
}
setup.py
from distutils.core import *
setup(
name="TestPythonExt", #打包文件名称
version="1.0",
ext_modules=[Extension("TestPythonExt", ["mymod.c"] )]
)
testmod.py
print("Test TestPythonExt Module")
#import TestPythonExt
from TestPythonExt import *
#print(help(mymod))
try:
#print(TestPythonExt.testmod(999, 555,33.44))
print(testmod(999, 555,33.44))
test_float("xx")
test_float(66.)
a = test_string("Python string to C++")
print("test_string return type is ",type(a))
print("test_string return= \" ", a,"\"")
test_kw(name="xiaoming1",age=20,score=100)
test_kw(name="xiaoming2")
test_kw("xiaoming3",15,70)
test_kw("xiaoming4",score=150)
tup = (1,2,4,5,6,7,8,9,10,11)
test_tuple(tup)
tup2 = (1,2,4,5,6,7,8,9,10,11,(99,88,77,66,55))
test_tuple(tup2)
re = test_tuple(tup)
print("\n=============retur===============")
print(re)
print("=========test list===========")
try:
test_list(111)
except Exception as e:
print("List Exception",type(e),e)
list1 = [0,1,2,3,4,5,6,7,8,9,10]
print("\nIn Python begin:",list1)
re = test_list(list1)
print("\nIn Python end:",list1)
print(re)
print("list1 id",id(list1), " re id=",id(re))
#返回值会被引用计数-1
test_list(list1)
print(list1)
#测试内存消耗
#while True:
dic = {"name":"xiaoming","age":20,"score":100,"title":"dic title","delkey":"delstring"}
print(dic)
re = test_dict(dic)
print("\n==========changed========")
print(dic)
print("=======re dict ========")
print(re)
except Exception as e:
print("Exception",type(e),e)
input()
1-myproject用到的关键技术
1-1头文件的引用
#include <Python.h>
//numpy转cv::Mat会使用到
#include <numpy/arrayobject.h>
1-2接收类型
static PyObject * MyFun(PyObject *self, PyObject *args) {
PyObject *image1, *image2;
if (!PyArg_ParseTuple(args, "OO", &image1, &image2)) {
return NULL;
}
PyObject* retval;
//https://docs.python.org/zh-cn/3.7/c-api/arg.html?highlight=py_buildvalue#c.Py_BuildValue
retval = (PyObject *)Py_BuildValue("i", 1000);
return retval;
//.......
//return ......
}
1-3ndarray转换为Mat
conversion.h
# ifndef __COVERSION_OPENCV_H__
# define __COVERSION_OPENCV_H__
#include <Python.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include "numpy/ndarrayobject.h"
#define NUMPY_IMPORT_ARRAY_RETVAL
static PyObject* opencv_error = 0;
static int failmsg(const char *fmt, ...);
class PyAllowThreads;
class PyEnsureGIL;
#define ERRWRAP2(expr) \
try \
{ \
PyAllowThreads allowThreads; \
expr; \
} \
catch (const cv::Exception &e) \
{ \
PyErr_SetString(opencv_error, e.what()); \
return 0; \
}
static PyObject* failmsgp(const char *fmt, ...);
static size_t REFCOUNT_OFFSET = (size_t)&(((PyObject*)0)->ob_refcnt) +
(0x12345678 != *(const size_t*)"\x78\x56\x34\x12\0\0\0\0\0")*sizeof(int);
static inline PyObject* pyObjectFromRefcount(const int* refcount)
{
return (PyObject*)((size_t)refcount - REFCOUNT_OFFSET);
}
static inline int* refcountFromPyObject(const PyObject* obj)
{
return (int*)((size_t)obj + REFCOUNT_OFFSET);
}
class NumpyAllocator;
enum { ARG_NONE = 0, ARG_MAT = 1, ARG_SCALAR = 2 };
class NDArrayConverter
{
private:
void init();
public:
NDArrayConverter();
cv::Mat toMat(const PyObject* o);
PyObject* toNDArray(const cv::Mat& mat);
};
# endif
MatAllocator
https://docs.opencv.org/3.4/df/d4c/classcv_1_1MatAllocator.html
mypack文件夹
conversion.cpp
# include "conversion.h"
/*
* The following conversion functions are taken/adapted from OpenCV's cv2.cpp file
* inside modules/python/src2 folder.
*/
static void init()
{
import_array();
}
static int failmsg(const char *fmt, ...)
{
char str[1000];
va_list ap;
va_start(ap, fmt);
vsnprintf(str, sizeof(str), fmt, ap);
va_end(ap);
PyErr_SetString(PyExc_TypeError, str);
return 0;
}
class PyAllowThreads
{
public:
PyAllowThreads() : _state(PyEval_SaveThread()) {}
~PyAllowThreads()
{
PyEval_RestoreThread(_state);
}
private:
PyThreadState* _state;
};
class PyEnsureGIL
{
public:
PyEnsureGIL() : _state(PyGILState_Ensure()) {}
~PyEnsureGIL()
{
PyGILState_Release(_state);
}
private:
PyGILState_STATE _state;
};
using namespace cv;
static PyObject* failmsgp(const char *fmt, ...)
{
char str[1000];
va_list ap;
va_start(ap, fmt);
vsnprintf(str, sizeof(str), fmt, ap);
va_end(ap);
PyErr_SetString(PyExc_TypeError, str);
return 0;
}
class NumpyAllocator : public MatAllocator
{
public:
NumpyAllocator() {}
~NumpyAllocator() {}
void allocate(int dims, const int* sizes, int type, int*& refcount,
uchar*& datastart, uchar*& data, size_t* step)
{
PyEnsureGIL gil;
int depth = CV_MAT_DEPTH(type);
int cn = CV_MAT_CN(type);
const int f = (int)(sizeof(size_t)/8);
int typenum = depth == CV_8U ? NPY_UBYTE : depth == CV_8S ? NPY_BYTE :
depth == CV_16U ? NPY_USHORT : depth == CV_16S ? NPY_SHORT :
depth == CV_32S ? NPY_INT : depth == CV_32F ? NPY_FLOAT :
depth == CV_64F ? NPY_DOUBLE : f*NPY_ULONGLONG + (f^1)*NPY_UINT;
int i;
npy_intp _sizes[CV_MAX_DIM+1];
for( i = 0; i < dims; i++ )
{
_sizes[i] = sizes[i];
}
if( cn > 1 )
{
_sizes[dims++] = cn;
}
PyObject* o = PyArray_SimpleNew(dims, _sizes, typenum);
if(!o)
{
CV_Error_(CV_StsError, ("The numpy array of typenum=%d, ndims=%d can not be created", typenum, dims));
}
refcount = refcountFromPyObject(o);
npy_intp* _strides = PyArray_STRIDES(o);
for( i = 0; i < dims - (cn > 1); i++ )
step[i] = (size_t)_strides[i];
datastart = data = (uchar*)PyArray_DATA(o);
}
void deallocate(int* refcount, uchar*, uchar*)
{
PyEnsureGIL gil;
if( !refcount )
return;
PyObject* o = pyObjectFromRefcount(refcount);
Py_INCREF(o);
Py_DECREF(o);
}
};
NumpyAllocator g_numpyAllocator;
NDArrayConverter::NDArrayConverter() { init(); }
void NDArrayConverter::init()
{
import_array();
}
cv::Mat NDArrayConverter::toMat(const PyObject *o)
{
cv::Mat m;
if(!o || o == Py_None)
{
if( !m.data )
m.allocator = &g_numpyAllocator;
}
if( !PyArray_Check(o) )
{
failmsg("toMat: Object is not a numpy array");
}
int typenum = PyArray_TYPE(o);
int type = typenum == NPY_UBYTE ? CV_8U : typenum == NPY_BYTE ? CV_8S :
typenum == NPY_USHORT ? CV_16U : typenum == NPY_SHORT ? CV_16S :
typenum == NPY_INT || typenum == NPY_LONG ? CV_32S :
typenum == NPY_FLOAT ? CV_32F :
typenum == NPY_DOUBLE ? CV_64F : -1;
if( type < 0 )
{
failmsg("toMat: Data type = %d is not supported", typenum);
}
int ndims = PyArray_NDIM(o);
if(ndims >= CV_MAX_DIM)
{
failmsg("toMat: Dimensionality (=%d) is too high", ndims);
}
int size[CV_MAX_DIM+1];
size_t step[CV_MAX_DIM+1], elemsize = CV_ELEM_SIZE1(type);
const npy_intp* _sizes = PyArray_DIMS(o);
const npy_intp* _strides = PyArray_STRIDES(o);
bool transposed = false;
for(int i = 0; i < ndims; i++)
{
size[i] = (int)_sizes[i];
step[i] = (size_t)_strides[i];
}
if( ndims == 0 || step[ndims-1] > elemsize ) {
size[ndims] = 1;
step[ndims] = elemsize;
ndims++;
}
if( ndims >= 2 && step[0] < step[1] )
{
std::swap(size[0], size[1]);
std::swap(step[0], step[1]);
transposed = true;
}
if( ndims == 3 && size[2] <= CV_CN_MAX && step[1] == elemsize*size[2] )
{
ndims--;
type |= CV_MAKETYPE(0, size[2]);
}
if( ndims > 2)
{
failmsg("toMat: Object has more than 2 dimensions");
}
m = Mat(ndims, size, type, PyArray_DATA(o), step);
if( m.data )
{
m.refcount = refcountFromPyObject(o);
m.addref(); // protect the original numpy array from deallocation
// (since Mat destructor will decrement the reference counter)
};
m.allocator = &g_numpyAllocator;
if( transposed )
{
Mat tmp;
tmp.allocator = &g_numpyAllocator;
transpose(m, tmp);
m = tmp;
}
return m;
}
PyObject* NDArrayConverter::toNDArray(const cv::Mat& m)
{
if( !m.data )
Py_RETURN_NONE;
Mat temp, *p = (Mat*)&m;
if(!p->refcount || p->allocator != &g_numpyAllocator)
{
temp.allocator = &g_numpyAllocator;
m.copyTo(temp);
p = &temp;
}
p->addref();
return pyObjectFromRefcount(p->refcount);
}
API
-
class NDArrayConverter
: The converter class -
NDArrayConverter::NDArrayConverter()
: Constructor -
cv::Mat NDArrayConverter::toMat(const PyObject* o)
: Convert a NumPy ndarray
to acv::Mat
.-
o is the object representing the Python representation of the ndarray.
-
Returns a
cv::Mat
which is the OpenCV representation of o.
-
-
PyObject* NDArrayConverter::toNDArray(const cv::Mat& mat)
: Convert acv::Mat
to a NumPy ndarray.-
mat is the cv::Mat to convert.
-
Returns a
PyObject*
that is the Python representation of an ndarray.
-
examples.cpp
#include <iostream>
#include <opencv2/imgproc/imgproc.hpp>
#include <boost/python.hpp>
#include "conversion.h"
namespace py = boost::python;
typedef unsigned char uchar_t;
/**
* Displays an image, passed in from python as an ndarray.
*/
void
display(PyObject *img)
{
NDArrayConverter cvt;
cv::Mat mat { cvt.toMat(img) };
cv::namedWindow("display", CV_WINDOW_NORMAL);
cv::imshow("display", mat);
cv::waitKey(0);
}
/**
* Converts a grayscale image to a bilevel image.
*/
PyObject*
binarize(PyObject *grayImg, short threshold)
{
NDArrayConverter cvt;
cv::Mat img { cvt.toMat(grayImg) };
for (int i = 0; i < img.rows; ++i)
{
uchar_t *ptr = img.ptr<uchar_t>(i);
for (int j = 0; j < img.cols; ++j)
{
ptr[j] = ptr[j] < threshold ? 0 : 255;
}
}
return cvt.toNDArray(img);
}
/**
* Multiplies two ndarrays by first converting them to cv::Mat and returns
* an ndarray containing the result back.
*/
PyObject*
mul(PyObject *left, PyObject *right)
{
NDArrayConverter cvt;
cv::Mat leftMat, rightMat;
leftMat = cvt.toMat(left);
rightMat = cvt.toMat(right);
auto r1 = leftMat.rows, c1 = leftMat.cols, r2 = rightMat.rows,
c2 = rightMat.cols;
// Work only with 2-D matrices that can be legally multiplied.
if (c1 != r2)
{
PyErr_SetString(PyExc_TypeError,
"Incompatible sizes for matrix multiplication.");
py::throw_error_already_set();
}
cv::Mat result = leftMat * rightMat;
PyObject* ret = cvt.toNDArray(result);
return ret;
}
static void init()
{
Py_Initialize();
import_array();
}
BOOST_PYTHON_MODULE(examples)
{
init();
py::def("display", display);
py::def("binarize", binarize);
py::def("mul", mul);
}
1-4转换代码的使用
static PyObject * MyFun(PyObject *self, PyObject *args) {
PyObject *image1, *image2;
if (!PyArg_ParseTuple(args, "OO", &image1, &image2)) {
return NULL;
}
cv::Mat grayimage = pbcvt::fromNDArrayToMat(image1);
cv::Mat depimage = pbcvt::fromNDArrayToMat(image2);
}
1-5传回python
例子1
static PyObject * MyFun(PyObject *self, PyObject *args) {
PyObject *image1, *image2;
if (!PyArg_ParseTuple(args, "OO", &image1, &image2)) {
return NULL;
}
PyObject* retval;
//https://docs.python.org/zh-cn/3.7/c-api/arg.html?highlight=py_buildvalue#c.Py_BuildValue
retval = (PyObject *)Py_BuildValue("i", 1000);
return retval;
//.......
//return ......
}
例子2
static PyObject *
TextStyle_New(TextStylePtr itself)
{
return Py_BuildValue("lllO&", (long)itself->tsFont, (long)itself->tsFace, (long)itself->tsSize, QdRGB_New,
&itself->tsColor);
}
例子3
Py_BuildValue("") None
Py_BuildValue("i", 123) 123
Py_BuildValue("iii", 123, 456, 789) (123, 456, 789)
Py_BuildValue("s", "hello") 'hello'
Py_BuildValue("ss", "hello", "world") ('hello', 'world')
Py_BuildValue("s#", "hello", 4) 'hell'
Py_BuildValue("()") ()
Py_BuildValue("(i)", 123) (123,)
Py_BuildValue("(ii)", 123, 456) (123, 456)
Py_BuildValue("(i,i)", 123, 456) (123, 456)
Py_BuildValue("[i,i]", 123, 456) [123, 456]
Py_BuildValue("{s:i,s:i}","abc", 123, "def", 456) {'abc': 123, 'def': 456}
Py_BuildValue("((ii)(ii)) (ii)", 1, 2, 3, 4, 5, 6) (((1, 2), (3, 4)), (5, 6))
1-6关于setup.py的依赖库问题
Py_BuildValue("") None
Py_BuildValue("i", 123) 123
Py_BuildValue("iii", 123, 456, 789) (123, 456, 789)
Py_BuildValue("s", "hello") 'hello'
Py_BuildValue("ss", "hello", "world") ('hello', 'world')
Py_BuildValue("s#", "hello", 4) 'hell'
Py_BuildValue("()") ()
Py_BuildValue("(i)", 123) (123,)
Py_BuildValue("(ii)", 123, 456) (123, 456)
Py_BuildValue("(i,i)", 123, 456) (123, 456)
Py_BuildValue("[i,i]", 123, 456) [123, 456]
Py_BuildValue("{s:i,s:i}","abc", 123, "def", 456) {'abc': 123, 'def': 456}
Py_BuildValue("((ii)(ii)) (ii)", 1, 2, 3, 4, 5, 6) (((1, 2), (3, 4)), (5, 6))
1-7关于Ubuntu安装多个opencv或其他库,系统优先级的问题
- 1通过apt-get安装了opencv
- 2通过源代码安装了opencv,直接make install
- 3通过源代码安装了opencv,指定install路径
以上这三种情况,我们该怎么使用各自的优先级
关于Windows直接可以更改Path中的先后顺序,那么Ubuntu16.04呢
- 1.vim /etc/ld.so.conf.d/
cuda.conf opencv.conf(我后加的)
fakeroot-x86_64-linux-gnu.conf x86_64-linux-gnu.conf
i386-linux-gnu.conf x86_64-linux-gnu_EGL.conf
i386-linux-gnu_GL.conf x86_64-linux-gnu_GL.conf
libc.conf zz_i386-biarch-compat.conf
- 2.vim /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf
关于上面这两个路径或文件,可以清晰看到,优先级最高的是
/etc/ld.so.conf
接着才是
/etc/ld.so.conf.d/
首先:
ubuntu 默认的PATH为
PATH=/home/brightman/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
apt-get和直接make install的链接库会安装在:
/lib/i386-linux-gnu
/usr/lib/i386-linux-gnu
/lib/i686-linux-gnu
/usr/lib/i686-linux-gnu
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu
/usr/local/lib
等一些地方,这些path,都会包含在/etc/ld.so.conf.d/中,那么相应的,也全部包含在/etc/ld.so.conf
所以如果你想要你自己设置路径的opencv优先级链接库查找,高于前面的情况,应该在/etc/ld.so.conf中的前面,去添加你的路径
/home/spple/CLionProjects/SIFT-GPU/bin
/media/spple/新加卷/Dataset/pcl-pcl-1.9.1/install/lib
/media/spple/新加卷1/opencv-3.4.8/install/lib
include /etc/ld.so.conf.d/*.con
修改完后可能还会出现问题,
ImportError: libopencv_core.so.3.4: cannot open shared object file: No such file or directory
这是由于没有更新修改后的lib:
sudo ldconfig -v
1-8关于Ubuntu下的debug问题
例子:
setup.py
from distutils.core import *
setup(
name="TestPythonExt", #打包文件名称
version="1.0",
ext_modules=[Extension("TestPythonExt", ["library.cpp"] )]
)
testmod.py
print("Test TestPythonExt Module")
import TestPythonExt
try:
print(TestPythonExt.testmod(999, 555))
except Exception as e:
print(e)
name = input()
print(name)
library.cpp
#include <iostream>
#include "Python.h"
///5 模块函数
static PyObject *testmod(PyObject *self,PyObject*args)
{
int x = 0;
int y = 0;
//失败会写入异常信息
if (!PyArg_ParseTuple(args, "ii", &x,&y))
{
printf("PyArg_ParseTuple");
return NULL; //会抛出异常
}
printf("PyArg_ParseTuple x = %d y = %d\n", x,y);
//返回python的long整形,c语言中引用计数+1,返回值交由python释放,
return PyLong_FromLong(105);
}
///4 模块函数列表
static PyMethodDef mymod_funcs[] = {
{
"testmod", //函数名称
testmod, //函数指针
METH_VARARGS,//多个参数 参数标识 无参数 METH_VARARGS METH_NOARGS
"testmod function." //函数说明 help(testmod)
},
{0,0,0,0}
};
///3 模块定义
static PyModuleDef mymod_module = {
PyModuleDef_HEAD_INIT,
"TestPythonExt", //模块名
"TestPythonExt is first module test", //模块说明 通过help(模块名)
-1, //模块空间,子解释器用,-1不使用
mymod_funcs //模块函数
};
///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名
PyMODINIT_FUNC PyInit_TestPythonExt(void)
{
printf("PyInit_TestPythonExt\n");
///2 模块创建函数 参数 PyModuleDef
return PyModule_Create(&mymod_module);
}
第一种无法调试的情况:
如果你使用扩展库,python setup.py install安装,那么不太方便直接debug
如果想要安装库
~/anaconda3/envs/py36_cpp_extension/bin/python setup.py build
~/anaconda3/envs/py36_cpp_extension/bin/python setup.py install --record log.txt
~/anaconda3/envs/py36_cpp_extension/bin/python testmod.py
如果想要删除库
cat log.txt | xargs rm -rf
log中的信息
/home/spple/anaconda3/envs/py36_cpp_extension/lib/python3.6/site-packages/TestPythonExt.cpython-36m-x86_64-linux-gnu.so
/home/spple/anaconda3/envs/py36_cpp_extension/lib/python3.6/site-packages/TestPythonExt-1.0-py3.6.egg-info
第二种可以调试的情况(clion):
动态库工程
CMakeLists.txt
cmake_minimum_required(VERSION 3.12)
project(TestPythonExt)
set(CMAKE_CXX_STANDARD 14)
#case1
#https://cmake.org/cmake/help/v3.6/module/FindPythonLibs.html
#find_package(PythonLibs REQUIRED)
#find_package(PythonLibs 3.6.7 EXACT REQUIRED)
#include_directories(${PYTHON_INCLUDE_DIRS})
#case2
set(PYTHONHOME /home/spple/anaconda3/envs/py36_cpp_extension)
include_directories(${PYTHONHOME}/include/python3.6m) #添加Python.h头文件路径
link_directories(${PYTHONHOME}/lib) #添加python动态链接库文件目录
add_library(TestPythonExt SHARED library.cpp)
#https://www.cnblogs.com/52php/p/5681755.html
#https://blog.csdn.net/weixin_34043301/article/details/92424326
#https://blog.csdn.net/tianyingang/article/details/94470546
#https://www.cnblogs.com/tangxin-blog/p/8283460.html
#cmake实践
set(LIBRARY_OUTPUT_PATH "${PYTHONHOME}/lib/python3.6/site-packages")
#更改名字不带lib*.so
#https://stackoverflow.com/questions/31038963/how-do-you-rename-a-library-filename-in-cmake
#https://cmake.org/cmake/help/v3.0/command/set_target_properties.html
#原始
#set_target_properties(TestPythonExt PROPERTIES LIBRARY_OUTPUT_NAME "TestPythonExt.cpython-36m-x86_64-linux-gnu")
#新方法 前缀+库名+后缀
set_target_properties(TestPythonExt PROPERTIES PREFIX "" SUFFIX ".cpython-36m-x86_64-linux-gnu.so")
#这种输出方式和python setup.py install生成的一样,虽然缺少一个#TestPythonExt-1.0-py3.6.egg-info 库信息文件,没有也没有关系
#case1
#target_link_libraries(TestPythonExt ${PYTHON_LIBRARIES})
#case2
target_link_libraries(TestPythonExt libpython3.6m.so) #依赖库文件
调试步骤:
- 步骤1:
- 步骤2:
- 步骤3:
- 步骤4:
1-9关于setup.py
普通版
setup.py
from distutils.core import *
setup(
name="TestPythonExt", #打包文件名称
version="1.0",
ext_modules=[Extension("TestPythonExt", ["library.cpp"] )]
)
- 官方版
https://docs.python.org/3/extending/building.html#building - 关于函数setup:distutils.core.setup(arguments)
https://docs.python.org/3/distutils/apiref.html#distutils.core.setup - 关于函数Extension:class distutils.core.Extension
https://docs.python.org/3/distutils/apiref.html#distutils.core.setup - Changed in version 3.8: On Unix, C extensions are no longer linked to libpython except on Android and Cygwin.
https://docs.python.org/dev/whatsnew/3.8.html
setup.py
from distutils.core import setup, Extension
module1 = Extension('demo',
sources = ['demo.c'])
setup (name = 'PackageName',
version = '1.0',
description = 'This is a demo package',
ext_modules = [module1])
from distutils.core import setup, Extension
module1 = Extension('demo',
define_macros = [('MAJOR_VERSION', '1'),
('MINOR_VERSION', '0')],
include_dirs = ['/usr/local/include'],
libraries = ['tcl83'],
library_dirs = ['/usr/local/lib'],
sources = ['demo.c'])
setup (name = 'PackageName',
version = '1.0',
description = 'This is a demo package',
author = 'Martin v. Loewis',
author_email = 'martin@v.loewis.de',
url = 'https://docs.python.org/extending/building',
long_description = '''This is really just a demo package.''',
ext_modules = [module1])
修改版
setup.py
from collections import defaultdict
from distutils.core import *
import numpy #include <numpy/arrayobject.h>
# ext新建
ext_args = defaultdict(list)
# numpy
ext_args['include_dirs'].append(numpy.get_include())
# opencv
opencv_inc_dir = '/media/spple/新加卷1/opencv-3.4.1/install_4/include'
opencv_lib_dir = '/media/spple/新加卷1/opencv-3.4.1/install_4/lib'
ext_args['include_dirs'].append(opencv_inc_dir)
ext_args['library_dirs'].append(opencv_lib_dir)
opencv_libs = ['opencv_core', 'opencv_calib3d', 'opencv_imgproc',
'opencv_imgcodecs', 'opencv_highgui', 'opencv_features2d',
'opencv_cudawarping','opencv_cudafeatures2d']
for librelease in opencv_libs:
ext_args['libraries'].append(librelease)
# eigen3
eigen3_inc_dir = '/usr/include/eigen3'
ext_args['include_dirs'].append(eigen3_inc_dir)
# pcl
pcl_version=1.9
pcl_include_dir = os.path.join('/media/spple/新加卷/Dataset/pcl-master/install/include/pcl-1.9')
pcl_library_dir = os.path.join('/media/spple/新加卷/Dataset/pcl-master/install/lib')
ext_args['include_dirs'].append(pcl_include_dir)
ext_args['library_dirs'].append(pcl_library_dir)
pcl_libs = ["common", "features", "filters",
"io", "io_ply", "kdtree", "keypoints", "octree", "outofcore", "people",
"recognition", "registration", "sample_consensus", "search",
"segmentation", "surface", "tracking", "visualization"]
pcl_libs = ["pcl_%s" % lib for lib in pcl_libs]
for librelease in pcl_libs:
ext_args['libraries'].append(librelease)
# OpenNI OpenNI2
ext_args['include_dirs'].append('/usr/include/ni')
ext_args['include_dirs'].append('/usr/include/openni2')
# vtk
vtk_version = '6.2'
vtk_include_dir = os.path.join('/usr/include/vtk-' + vtk_version)
vtk_library_dir = os.path.join('/usr/lib/x86_64-linux-gnu')
ext_args['include_dirs'].append(vtk_include_dir)
ext_args['library_dirs'].append(vtk_library_dir)
vtk_version = '6.2'
vtklibreleases = ['vtkalglib-' + vtk_version, 'vtkChartsCore-' + vtk_version, 'vtkCommonColor-' + vtk_version,
'vtkCommonComputationalGeometry-' + vtk_version, 'vtkCommonCore-' + vtk_version,
'vtkCommonDataModel-' + vtk_version, 'vtkCommonExecutionModel-' + vtk_version,
'vtkCommonMath-' + vtk_version, 'vtkCommonMisc-' + vtk_version, 'vtkCommonSystem-' + vtk_version,
'vtkCommonTransforms-' + vtk_version, 'vtkDICOMParser-' + vtk_version,
'vtkDomainsChemistry-' + vtk_version, 'vtkexoIIc-' + vtk_version,
'vtkFiltersAMR-' + vtk_version, 'vtkFiltersCore-' + vtk_version,
'vtkFiltersExtraction-' + vtk_version, 'vtkFiltersFlowPaths-' + vtk_version,
'vtkFiltersGeneral-' + vtk_version, 'vtkFiltersGeneric-' + vtk_version,
'vtkFiltersGeometry-' + vtk_version, 'vtkFiltersHybrid-' + vtk_version,
'vtkFiltersHyperTree-' + vtk_version, 'vtkFiltersImaging-' + vtk_version,
'vtkFiltersModeling-' + vtk_version, 'vtkFiltersParallel-' + vtk_version,
'vtkFiltersParallelImaging-' + vtk_version, 'vtkFiltersProgrammable-' + vtk_version,
'vtkFiltersSelection-' + vtk_version, 'vtkFiltersSMP-' + vtk_version,
'vtkFiltersSources-' + vtk_version, 'vtkFiltersStatistics-' + vtk_version,
'vtkFiltersTexture-' + vtk_version, 'vtkFiltersVerdict-' + vtk_version,
'vtkGeovisCore-' + vtk_version,
'vtkImagingColor-' + vtk_version, 'vtkImagingCore-' + vtk_version,
'vtkImagingFourier-' + vtk_version, 'vtkImagingGeneral-' + vtk_version,
'vtkImagingHybrid-' + vtk_version, 'vtkImagingMath-' + vtk_version,
'vtkImagingMorphological-' + vtk_version, 'vtkImagingSources-' + vtk_version,
'vtkImagingStatistics-' + vtk_version, 'vtkImagingStencil-' + vtk_version,
'vtkInfovisCore-' + vtk_version, 'vtkInfovisLayout-' + vtk_version,
'vtkInteractionImage-' + vtk_version, 'vtkInteractionStyle-' + vtk_version,
'vtkInteractionWidgets-' + vtk_version, 'vtkIOAMR-' + vtk_version, 'vtkIOCore-' + vtk_version,
'vtkIOEnSight-' + vtk_version, 'vtkIOExodus-' + vtk_version, 'vtkIOExport-' + vtk_version,
'vtkIOGeometry-' + vtk_version, 'vtkIOImage-' + vtk_version, 'vtkIOImport-' + vtk_version,
'vtkIOInfovis-' + vtk_version, 'vtkIOLegacy-' + vtk_version, 'vtkIOLSDyna-' + vtk_version,
'vtkIOMINC-' + vtk_version, 'vtkIOMovie-' + vtk_version, 'vtkIONetCDF-' + vtk_version,
'vtkIOParallel-' + vtk_version, 'vtkIOParallelXML-' + vtk_version, 'vtkIOPLY-' + vtk_version,
'vtkIOSQL-' + vtk_version, 'vtkIOVideo-' + vtk_version, 'vtkIOXML-' + vtk_version,
'vtkIOXMLParser-' + vtk_version,
'vtkmetaio-' + vtk_version,
'vtkParallelCore-' + vtk_version,
'vtkRenderingAnnotation-' + vtk_version,
'vtkRenderingContext2D-' + vtk_version, 'vtkRenderingContextOpenGL-' + vtk_version,
'vtkRenderingCore-' + vtk_version, 'vtkRenderingFreeType-' + vtk_version,
'vtkRenderingGL2PS-' + vtk_version, 'vtkRenderingImage-' + vtk_version,
'vtkRenderingLabel-' + vtk_version, 'vtkRenderingLIC-' + vtk_version,
'vtkRenderingLOD-' + vtk_version, 'vtkRenderingOpenGL-' + vtk_version,
'vtkRenderingVolume-' + vtk_version, 'vtkRenderingVolumeOpenGL-' + vtk_version,
'vtksys-' + vtk_version,
'vtkverdict-' + vtk_version, 'vtkViewsContext2D-' + vtk_version, 'vtkViewsCore-' + vtk_version,
'vtkViewsInfovis-' + vtk_version]
for librelease in vtklibreleases:
ext_args['libraries'].append(librelease)
# 编译器
ext_args['extra_compile_args'].append("-std=c++14")
module = [Extension("TestPythonExt",
["library.cpp"],
language="c++",
**ext_args)]
setup(
name='TestPythonExt',
version="1.0",
ext_modules=module})
2关于.cpp文件中怎么传回到Python
static PyObject * MyFun(PyObject *self, PyObject *args) {
PyObject *image1, *image2;
if (!PyArg_ParseTuple(args, "OO", &image1, &image2)) {
return NULL;
}
PyObject* retval;
//https://docs.python.org/zh-cn/3.7/c-api/arg.html?highlight=py_buildvalue#c.Py_BuildValue
retval = (PyObject *)Py_BuildValue("i", 1000);
return retval;
//.......
//return ......
}