zoukankan      html  css  js  c++  java
  • [C++/Python] 如何在C++中使用一个Python类? (Use Python-defined class in C++)

    最近在做基于OpenCV的车牌识别, 其中需要用到深度学习的一些代码(Python), 所以一开始的时候开发语言选择了Python(祸患之源).

    固然现在Python的速度不算太慢, 但你一定要用Python来操作图像, 实现某些算法的时候, 效率就变得非常重要. 可惜的是, Python在大多数算法实现中, 由于其循环操作实在是太慢, 导致实现的算法效率非常之低.

    所以现在我要把深度学习中的一个类(分类器)转换到C++中, 在这个过程之前, 需要做一些test projects, 我主要参照的文章是: C++调用Python(3).

    开发环境为 VS2012, WIN7 64.

    所有代码都在最后放出, 这里先逐步讲解.

    首先我们需要导入合适的头文件: Python.h, 它位于你的Python安装目录的include目录下. (2.6, 2.7版本实测通过)

    使用VS的话, 可以按如下方法设置一下项目属性:

    1. 调试 -> xxx属性(最后一栏) -> VC++目录 -> 右侧库目录
    2. 增加C:Python27libs, 具体路径个人可能不同.

    这样就完成了最基本的配置, 下面我们开始导入.py文件并使用它.

    我们使用的.py文件非常简单, 代码如下:

     1 #!/usr/bin/python
     2 # Filename: testpy.py
     3 class Person:
     4     def sayHi(self):
     5         print 'hi'
     6 class Second:
     7     def invoke(self,obj):
     8          obj.sayHi()
     9 def sayhi(name):
    10     print 'hi',name;

    注: 下述所有导入方法在导入失败时不会报错, 只会返回空指针.

    第一步是导入.py文件:

    1. 使用PyObject* pModule来存储导入的.py文件模块, 调用的方法是PyImport_ImportModule(path):  PyObject* pModule = PyImport_ImportModule("testpy"); 
    2. 使用PyObject* pDict来存储导入模块中的方法字典, 调用的方法是PyModule_GetDict(module):  PyObject* pDict = PyModule_GetDict(pModule); 

    这样就完成了.py文件的导入.

    第二步是导入已导入模块中的方法或类:

    1. 获取方法, 调用的方法是PyDict_GetItemString(dict, methodName): PyObject* pFunHi = PyDict_GetItemString(pDict, "sayhi"); 
    2. 获取类, 调用的方法同上, 注意红体部分的字符串对应于.py文件中的类/方法名:  PyObject* pClassSecond = PyDict_GetItemString(pDict, "Second"); 

    第三步是使用导入的方法或类:

    1. 使用方法, 调用PyObject_CallFunction(pFunc, "s", args)即可:  PyObject_CallFunction(pFunHi, "s", "lhb"); 
    2. 使用类构造对象, 调用PyInstance_New(pClass, NULL, NULL)即可:  PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL); , 注意其中的pClassSecond为第二步.2中获取的类指针
    3. 使用类对象的方法, 调用PyObject_CallMethod(pInstance, methodname, "O", args)即可:  PyObject_CallMethod(pInstanceSecond, "invoke", "O", pInstancePerson); 
    4. 上述调用中的"s"和"O"代表的是参数列表的类型, 我们可以在 Py_BuildValue 找到所有的类型, 本文最后也附了此表.

    最后不要忘记销毁这些对象:  Py_DECREF(pointer); 

    下面是C++的实现代码, 代码来自于我参考的博客, 略有修改.

     

     1 /*
     2  * test.cpp
     3  *  Created on: 2010-8-12
     4  *      Author: lihaibo
     5  */
     6 #include <C:/Python27/include/Python.h>
     7 #include <iostream>
     8 #include <string>
     9 
    10 int main(void) {
    11     Py_Initialize(); // 启动虚拟机
    12     if (!Py_IsInitialized())
    13         return -1;
    14     // 导入模块
    15     PyObject* pModule = PyImport_ImportModule("testpy");
    16     if (!pModule) {
    17         printf("Cant open python file!/n");
    18         return -1;
    19     }
    20     // 模块的字典列表
    21     PyObject* pDict = PyModule_GetDict(pModule);
    22     if (!pDict) {
    23         printf("Cant find dictionary./n");
    24         return -1;
    25     }
    26     // 演示函数调用
    27     PyObject* pFunHi = PyDict_GetItemString(pDict, "sayhi");
    28     PyObject_CallFunction(pFunHi, "s", "lhb");
    29     Py_DECREF(pFunHi);
    30     // 演示构造一个Python对象,并调用Class的方法
    31     // 获取Second类
    32     PyObject* pClassSecond = PyDict_GetItemString(pDict, "Second");
    33     if (!pClassSecond) {
    34         printf("Cant find second class./n");
    35         return -1;
    36     }
    37     //获取Person类
    38     PyObject* pClassPerson = PyDict_GetItemString(pDict, "Person");
    39     if (!pClassPerson) {
    40         printf("Cant find person class./n");
    41         return -1;
    42     }
    43     //构造Second的实例
    44     PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL);
    45     if (!pInstanceSecond) {
    46         printf("Cant create second instance./n");
    47         return -1;
    48     }
    49     //构造Person的实例
    50     PyObject* pInstancePerson = PyInstance_New(pClassPerson, NULL, NULL);
    51     if (!pInstancePerson) {
    52         printf("Cant find person instance./n");
    53         return -1;
    54     }
    55     //把person实例传入second的invoke方法
    56     PyObject_CallMethod(pInstanceSecond, "invoke", "O", pInstancePerson);
    57     //释放
    58     Py_DECREF(pInstanceSecond);
    59     Py_DECREF(pInstancePerson);
    60     Py_DECREF(pClassSecond);
    61     Py_DECREF(pClassPerson);
    62     Py_DECREF(pModule);
    63     Py_Finalize(); // 关闭虚拟机
    64     return 0;
    65 }

     类型参照:

    s (string) [char *]
    Convert a null-terminated C string to a Python object. If the C string pointer is NULLNone 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 NULLNoneis 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) [converteranything]
    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.

  • 相关阅读:
    keycloak~管理平台的查询bug与自定rest中文检索
    gRPC四种模式、认证和授权,C#实战演示
    asp.net core 集成JWT
    从不同使用场景来介绍git的基础命令
    用scikit-learn进行LDA降维——以前没有注意,原来LDA降维竟然这么好用!对无监督的任务使用PCA进行降维,对有监督的则应用LDA。
    ID3/Cart/C4.5区别
    超参数调优——google Vizier采用迁移学习的思想,主要是从之前调参的经验中学习,为新算法提出最佳超参数
    sklearn 绘制roc曲线
    原来ROC曲线更加健壮地反映模型的效果,看来还是比较关键的(就像逻辑回归,你总是希望模型让0/1分类的数据尽可能都向两端靠对不对,ROC就是反映这个好坏的指标)
    word2vec的原理——根据单词的上下文去预测单词出现,然后让整体的概率最大化。学习这样一个神经网络,然后选择隐藏作为vector表示。最初单词是onehot编码!
  • 原文地址:https://www.cnblogs.com/lancelod/p/4036922.html
Copyright © 2011-2022 走看看