[C++/Python] 如何在C++中使用一个Python类? (Use Python-defined class in C++)
2014-10-20 12:35
537 查看
最近在做基于OpenCV的车牌识别, 其中需要用到深度学习的一些代码(Python), 所以一开始的时候开发语言选择了Python(祸患之源).
固然现在Python的速度不算太慢, 但你一定要用Python来操作图像, 实现某些算法的时候, 效率就变得非常重要. 可惜的是, Python在大多数算法实现中, 由于其循环操作实在是太慢, 导致实现的算法效率非常之低.
所以现在我要把深度学习中的一个类(分类器)转换到C++中, 在这个过程之前, 需要做一些test projects, 我主要参照的文章是: C++调用Python(3).
开发环境为 VS2012, WIN7 64.
所有代码都在最后放出, 这里先逐步讲解.
首先我们需要导入合适的头文件: Python.h, 它位于你的Python安装目录的include目录下. (2.6, 2.7版本实测通过)
使用VS的话, 可以按如下方法设置一下项目属性:
调试 -> xxx属性(最后一栏) -> VC++目录 -> 右侧库目录
增加C:\Python27\libs, 具体路径个人可能不同.
这样就完成了最基本的配置, 下面我们开始导入.py文件并使用它.
我们使用的.py文件非常简单, 代码如下:
注: 下述所有导入方法在导入失败时不会报错, 只会返回空指针.
第一步是导入.py文件:
使用PyObject* pModule来存储导入的.py文件模块, 调用的方法是PyImport_ImportModule(path): PyObject* pModule = PyImport_ImportModule("testpy");
使用PyObject* pDict来存储导入模块中的方法字典, 调用的方法是PyModule_GetDict(module): PyObject* pDict = PyModule_GetDict(pModule);
这样就完成了.py文件的导入.
第二步是导入已导入模块中的方法或类:
获取方法, 调用的方法是PyDict_GetItemString(dict, methodName): PyObject* pFunHi = PyDict_GetItemString(pDict, "sayhi");
获取类, 调用的方法同上, 注意红体部分的字符串对应于.py文件中的类/方法名: PyObject* pClassSecond = PyDict_GetItemString(pDict, "Second");
第三步是使用导入的方法或类:
使用方法, 调用PyObject_CallFunction(pFunc, "s", args)即可: PyObject_CallFunction(pFunHi, "s", "lhb");
使用类构造对象, 调用PyInstance_New(pClass, NULL, NULL)即可: PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL); , 注意其中的pClassSecond为第二步.2中获取的类指针
使用类对象的方法, 调用PyObject_CallMethod(pInstance, methodname, "O", args)即可: PyObject_CallMethod(pInstanceSecond, "invoke", "O", pInstancePerson);
上述调用中的"s"和"O"代表的是参数列表的类型, 我们可以在 Py_BuildValue 找到所有的类型, 本文最后也附了此表.
最后不要忘记销毁这些对象: Py_DECREF(pointer);
下面是C++的实现代码, 代码来自于我参考的博客, 略有修改.
类型参照:
s (string) [char *]Convert a null-terminated C string to a Python object. If the C string pointer is NULL, None is used.s# (string) [char *, int]Convert a C string and its length to a Python object. If the C string pointer is NULL, the length is ignored and None is returned.z (string or None) [char *]Same as s.z# (string or None) [char *, int]Same as s#.u (Unicode string) [Py_UNICODE *]Convert a null-terminated buffer of Unicode (UCS-2 or UCS-4) data to a Python Unicode object. If the Unicode buffer pointer is NULL, Noneis returned.u# (Unicode string) [Py_UNICODE *, int]Convert a Unicode (UCS-2 or UCS-4) data buffer and its length to a Python Unicode object. If the Unicode buffer pointer is NULL, the length is ignored and None is returned.i (integer) [int]Convert a plain C int to a Python integer object.b (integer) [char]Convert a plain C char to a Python integer object.h (integer) [short int]Convert a plain C short int to a Python integer object.l (integer) [long int]Convert a C long int to a Python integer object.B (integer) [unsigned char]Convert a C unsigned char to a Python integer object.H (integer) [unsigned short int]Convert a C unsigned short int to a Python integer object.I (integer/long) [unsigned int]Convert a C unsigned int to a Python integer object or a Python long integer object, if it is larger than sys.maxint.k (integer/long) [unsigned long]Convert a C unsigned long to a Python integer object or a Python long integer object, if it is larger than sys.maxint.L (long) [PY_LONG_LONG]Convert a C long long to a Python long integer object. Only available on platforms that support long long.K (long) [unsigned PY_LONG_LONG]Convert a C unsigned long long to a Python long integer object. Only available on platforms that support unsigned long long.n (int) [Py_ssize_t]
Convert a C Py_ssize_t to a Python integer or long integer.
New in version 2.5.
c (string of length 1) [char]Convert a C int representing a character to a Python string of length 1.d (float) [double]Convert a C double to a Python floating point number.f (float) [float]Same as d.D (complex) [Py_complex *]Convert a C Py_complex structure to a Python complex number.O (object) [PyObject *]Pass a Python object untouched (except for its reference count, which is incremented by one). If the object passed in is a NULL pointer, it is assumed that this was caused because the call producing the argument found an error and set an exception. Therefore, Py_BuildValue()will return NULL but won’t raise an exception. If no exception has been raised yet, SystemError is set.S (object) [PyObject *]Same as O.N (object) [PyObject *]Same as O, except it doesn’t increment the reference count on the object. Useful when the object is created by a call to an object constructor in the argument list.O& (object) [converter, anything]Convert anything to a Python object through a converter function. The function is called with anything (which should be compatible withvoid *) as its argument and should return a “new” Python object, or NULL if an error occurred.(items) (tuple) [matching-items]Convert a sequence of C values to a Python tuple with the same number of items.[items] (list) [matching-items]Convert a sequence of C values to a Python list with the same number of items.{items} (dictionary) [matching-items]Convert a sequence of C values to a Python dictionary. Each pair of consecutive C values adds one item to the dictionary, serving as key and value, respectively.
If there is an error in the format string, the SystemError exception is set and NULL returned.
固然现在Python的速度不算太慢, 但你一定要用Python来操作图像, 实现某些算法的时候, 效率就变得非常重要. 可惜的是, Python在大多数算法实现中, 由于其循环操作实在是太慢, 导致实现的算法效率非常之低.
所以现在我要把深度学习中的一个类(分类器)转换到C++中, 在这个过程之前, 需要做一些test projects, 我主要参照的文章是: C++调用Python(3).
开发环境为 VS2012, WIN7 64.
所有代码都在最后放出, 这里先逐步讲解.
首先我们需要导入合适的头文件: Python.h, 它位于你的Python安装目录的include目录下. (2.6, 2.7版本实测通过)
使用VS的话, 可以按如下方法设置一下项目属性:
调试 -> xxx属性(最后一栏) -> VC++目录 -> 右侧库目录
增加C:\Python27\libs, 具体路径个人可能不同.
这样就完成了最基本的配置, 下面我们开始导入.py文件并使用它.
我们使用的.py文件非常简单, 代码如下:
#!/usr/bin/python # Filename: testpy.py class Person: def sayHi(self): print 'hi' class Second: def invoke(self,obj): obj.sayHi() def sayhi(name): print 'hi',name;
注: 下述所有导入方法在导入失败时不会报错, 只会返回空指针.
第一步是导入.py文件:
使用PyObject* pModule来存储导入的.py文件模块, 调用的方法是PyImport_ImportModule(path): PyObject* pModule = PyImport_ImportModule("testpy");
使用PyObject* pDict来存储导入模块中的方法字典, 调用的方法是PyModule_GetDict(module): PyObject* pDict = PyModule_GetDict(pModule);
这样就完成了.py文件的导入.
第二步是导入已导入模块中的方法或类:
获取方法, 调用的方法是PyDict_GetItemString(dict, methodName): PyObject* pFunHi = PyDict_GetItemString(pDict, "sayhi");
获取类, 调用的方法同上, 注意红体部分的字符串对应于.py文件中的类/方法名: PyObject* pClassSecond = PyDict_GetItemString(pDict, "Second");
第三步是使用导入的方法或类:
使用方法, 调用PyObject_CallFunction(pFunc, "s", args)即可: PyObject_CallFunction(pFunHi, "s", "lhb");
使用类构造对象, 调用PyInstance_New(pClass, NULL, NULL)即可: PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL); , 注意其中的pClassSecond为第二步.2中获取的类指针
使用类对象的方法, 调用PyObject_CallMethod(pInstance, methodname, "O", args)即可: PyObject_CallMethod(pInstanceSecond, "invoke", "O", pInstancePerson);
上述调用中的"s"和"O"代表的是参数列表的类型, 我们可以在 Py_BuildValue 找到所有的类型, 本文最后也附了此表.
最后不要忘记销毁这些对象: Py_DECREF(pointer);
下面是C++的实现代码, 代码来自于我参考的博客, 略有修改.
/* * test.cpp * Created on: 2010-8-12 * Author: lihaibo */ #include <C:/Python27/include/Python.h> #include <iostream> #include <string> int main(void) { Py_Initialize(); // 启动虚拟机 if (!Py_IsInitialized()) return -1; // 导入模块 PyObject* pModule = PyImport_ImportModule("testpy"); if (!pModule) { printf("Cant open python file!/n"); return -1; } // 模块的字典列表 PyObject* pDict = PyModule_GetDict(pModule); if (!pDict) { printf("Cant find dictionary./n"); return -1; } // 演示函数调用 PyObject* pFunHi = PyDict_GetItemString(pDict, "sayhi"); PyObject_CallFunction(pFunHi, "s", "lhb"); Py_DECREF(pFunHi); // 演示构造一个Python对象,并调用Class的方法 // 获取Second类 PyObject* pClassSecond = PyDict_GetItemString(pDict, "Second"); if (!pClassSecond) { printf("Cant find second class./n"); return -1; } //获取Person类 PyObject* pClassPerson = PyDict_GetItemString(pDict, "Person"); if (!pClassPerson) { printf("Cant find person class./n"); return -1; } //构造Second的实例 PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL); if (!pInstanceSecond) { printf("Cant create second instance./n"); return -1; } //构造Person的实例 PyObject* pInstancePerson = PyInstance_New(pClassPerson, NULL, NULL); if (!pInstancePerson) { printf("Cant find person instance./n"); return -1; } //把person实例传入second的invoke方法 PyObject_CallMethod(pInstanceSecond, "invoke", "O", pInstancePerson); //释放 Py_DECREF(pInstanceSecond); Py_DECREF(pInstancePerson); Py_DECREF(pClassSecond); Py_DECREF(pClassPerson); Py_DECREF(pModule); Py_Finalize(); // 关闭虚拟机 return 0; }
类型参照:
s (string) [char *]Convert a null-terminated C string to a Python object. If the C string pointer is NULL, None is used.s# (string) [char *, int]Convert a C string and its length to a Python object. If the C string pointer is NULL, the length is ignored and None is returned.z (string or None) [char *]Same as s.z# (string or None) [char *, int]Same as s#.u (Unicode string) [Py_UNICODE *]Convert a null-terminated buffer of Unicode (UCS-2 or UCS-4) data to a Python Unicode object. If the Unicode buffer pointer is NULL, Noneis returned.u# (Unicode string) [Py_UNICODE *, int]Convert a Unicode (UCS-2 or UCS-4) data buffer and its length to a Python Unicode object. If the Unicode buffer pointer is NULL, the length is ignored and None is returned.i (integer) [int]Convert a plain C int to a Python integer object.b (integer) [char]Convert a plain C char to a Python integer object.h (integer) [short int]Convert a plain C short int to a Python integer object.l (integer) [long int]Convert a C long int to a Python integer object.B (integer) [unsigned char]Convert a C unsigned char to a Python integer object.H (integer) [unsigned short int]Convert a C unsigned short int to a Python integer object.I (integer/long) [unsigned int]Convert a C unsigned int to a Python integer object or a Python long integer object, if it is larger than sys.maxint.k (integer/long) [unsigned long]Convert a C unsigned long to a Python integer object or a Python long integer object, if it is larger than sys.maxint.L (long) [PY_LONG_LONG]Convert a C long long to a Python long integer object. Only available on platforms that support long long.K (long) [unsigned PY_LONG_LONG]Convert a C unsigned long long to a Python long integer object. Only available on platforms that support unsigned long long.n (int) [Py_ssize_t]
Convert a C Py_ssize_t to a Python integer or long integer.
New in version 2.5.
c (string of length 1) [char]Convert a C int representing a character to a Python string of length 1.d (float) [double]Convert a C double to a Python floating point number.f (float) [float]Same as d.D (complex) [Py_complex *]Convert a C Py_complex structure to a Python complex number.O (object) [PyObject *]Pass a Python object untouched (except for its reference count, which is incremented by one). If the object passed in is a NULL pointer, it is assumed that this was caused because the call producing the argument found an error and set an exception. Therefore, Py_BuildValue()will return NULL but won’t raise an exception. If no exception has been raised yet, SystemError is set.S (object) [PyObject *]Same as O.N (object) [PyObject *]Same as O, except it doesn’t increment the reference count on the object. Useful when the object is created by a call to an object constructor in the argument list.O& (object) [converter, anything]Convert anything to a Python object through a converter function. The function is called with anything (which should be compatible withvoid *) as its argument and should return a “new” Python object, or NULL if an error occurred.(items) (tuple) [matching-items]Convert a sequence of C values to a Python tuple with the same number of items.[items] (list) [matching-items]Convert a sequence of C values to a Python list with the same number of items.{items} (dictionary) [matching-items]Convert a sequence of C values to a Python dictionary. Each pair of consecutive C values adds one item to the dictionary, serving as key and value, respectively.
If there is an error in the format string, the SystemError exception is set and NULL returned.
相关文章推荐
- 如何在python中使用*args,**kwargs (How to use *args and **kwargs in Python)
- How to use toolbar control on dialog using CToolBar class in VC++ - VC++ 中用CToolBar 类如何使用ToolBar控件
- [C++/Python] 如何在Python中使用一个DLL? (Windows环境)
- 如何在C++中使用VBScript(使用Qt)--How to use VBScript in C++ (Using Qt)
- 让C++和Python使用同一个枚举
- 如何在Vista中使用MMC方式的Remote Desktops(How to use Remote Desktops through mmc console in Vista)
- 一个使用C++写好的程序,c程序如何使用?
- HowTo use linux laptop in presentations 【如何在Linux系统上使用投影仪】
- (译)如何使用SocketAsyncEventArgs类(How to use the SocketAsyncEventArgs class)
- 一个实用主义者的观点:如何学习使用C++
- [转]How to use String.Format in PowerShell?(如何在PowerShell中使用string.format?)
- C++和Python使用同一个枚举的方法
- 译文:如何使用SocketAsyncEventArgs类(How to use the SocketAsyncEventArgs class) (转)
- How to use ComboBox Control in VC++ - 在VC中如何使用 ComboBox 控件
- 如何使用Python为Hadoop编写一个简单的MapReduce程序(这个人T字还有好几篇精华的可以看)
- 15.如何在同一个程序中混合使用C++和C
- java中如何使用asm动态的生成或修改一个class文件以及asm的架构思想
- [Ubuntu] 如何在VirtualBox OSE中使用share folders -- How to use the share folders in VirtualBox OSE
- 如何学习使用C++一个实用主义者的观点
- [转载]如何使用SocketAsyncEventArgs类(How to use the SocketAsyncEventArgs class)