clion-python扩展库-debug调试-python&cpp联合编程-ndarray互转cv::Mat


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 a cv::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 a cv::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"] )]
)

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 ......
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值