最近在做基于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:\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文件:

  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++的实现代码, 代码来自于我参考的博客, 略有修改.

 /*
* 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 -;
// 导入模块
PyObject* pModule = PyImport_ImportModule("testpy");
if (!pModule) {
printf("Cant open python file!/n");
return -;
}
// 模块的字典列表
PyObject* pDict = PyModule_GetDict(pModule);
if (!pDict) {
printf("Cant find dictionary./n");
return -;
}
// 演示函数调用
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 -;
}
//获取Person类
PyObject* pClassPerson = PyDict_GetItemString(pDict, "Person");
if (!pClassPerson) {
printf("Cant find person class./n");
return -;
}
//构造Second的实例
PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL);
if (!pInstanceSecond) {
printf("Cant create second instance./n");
return -;
}
//构造Person的实例
PyObject* pInstancePerson = PyInstance_New(pClassPerson, NULL, NULL);
if (!pInstancePerson) {
printf("Cant find person instance./n");
return -;
}
//把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 ;
}

类型参照:

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.

[C++/Python] 如何在C++中使用一个Python类? (Use Python-defined class in C++)的更多相关文章

  1. 如何在JAVA中实现一个固定最大size的hashMap

    如何在JAVA中实现一个固定最大size的hashMap 利用LinkedHashMap的removeEldestEntry方法,重载此方法使得这个map可以增长到最大size,之后每插入一条新的记录 ...

  2. 如何在idea中引入一个新maven项目

    如何在idea中引入一个新的maven项目,请参见如下操作:      

  3. 如何在html中把一个图片或者表格覆盖在一张已有图片上的任意位置

    如何在html中把一个图片或者表格覆盖在一张已有图片上的任意位置   <div style="position:relative;"> <img src=&quo ...

  4. (转)如何在Linux中统计一个进程的线程数

    如何在Linux中统计一个进程的线程数 原文:http://os.51cto.com/art/201509/491728.htm 我正在运行一个程序,它在运行时会派生出多个线程.我想知道程序在运行时会 ...

  5. Kubernetes入门(四)——如何在Kubernetes中部署一个可对外服务的Tensorflow机器学习模型

    机器学习模型常用Docker部署,而如何对Docker部署的模型进行管理呢?工业界的解决方案是使用Kubernetes来管理.编排容器.Kubernetes的理论知识不是本文讨论的重点,这里不再赘述, ...

  6. Python多进程库multiprocessing中进程池Pool类的使用[转]

    from:http://blog.csdn.net/jinping_shi/article/details/52433867 Python多进程库multiprocessing中进程池Pool类的使用 ...

  7. Python的Django框架中forms表单类的使用方法详解

    用户表单是Web端的一项基本功能,大而全的Django框架中自然带有现成的基础form对象,本文就Python的Django框架中forms表单类的使用方法详解. Form表单的功能 自动生成HTML ...

  8. Entity Framework 的小实例:在项目中添加一个实体类,并做插入操作

    Entity Framework 的小实例:在项目中添加一个实体类,并做插入操作 1>. 创建一个控制台程序2>. 添加一个 ADO.NET实体数据模型,选择对应的数据库与表(Studen ...

  9. 在存放源程序的文件夹中建立一个子文件夹 myPackage。例如,在“D:\java”文件夹之中创建一个与包同名的子文件夹 myPackage(D:\java\myPackage)。在 myPackage 包中创建一个YMD类,该类具有计算今年的年份、可以输出一个带有年月日的字符串的功能。设计程序SY31.java,给定某人姓名和出生日期,计算该人年龄,并输出该人姓名、年龄、出生日期。程序使用YM

    题目补充: 在存放源程序的文件夹中建立一个子文件夹 myPackage.例如,在“D:\java”文件夹之中创建一个与包同名的子文件夹 myPackage(D:\java\myPackage).在 m ...

随机推荐

  1. Java使用Sockt进行通信(2)

    使用TCP协议编写Sockt TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议,由IETF的RFC 793定义. ...

  2. GitHub的Windows客户端的使用教程

    GitHub for Windows客户端的使用教程 什么是Github >说到什么是GitHub,我们先看wikipedia的描述“GitHub是一个利用Git进行版本控制.专门用于存放软件代 ...

  3. Linux ssh下实现免密码登录

    1.Linux 生成密钥 ssh-keygen -t rsa 进入“.ssh”会生成以下几个文件 id_rsa : 生成的私钥文件 id_rsa.pub : 生成的公钥文件 know_hosts : ...

  4. 2016 Russian Code Cup (RCC 16), Final Round B - Cactusophobia

    B - Cactusophobia 思路: 点双联通分量+最大流 用tarjan求出每个点双联通分量 对于大小大于1的点双联通分量,它就是个环,那么源点和这个环相连, 容量为环的大小减一,这个环和环上 ...

  5. vue-循环并获取dom元素

    <ul class="picBox"> <li v-for="(item,index) in picArr" ><img :src ...

  6. Asp.net core (学习笔记 路由和语言 route & language)

    https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-2.1 https://doc ...

  7. HihoCoder - 1142 ,三分入门

    先来说说三分的思想: 从三分法的名字中我们可以猜到,三分法是对于需要逼近的区间做三等分: 我们发现lm这个点比rm要低,那么我们要找的最小点一定在[left,rm]之间.如果最低点在[rm,right ...

  8. Android中如何解决editText一进入activity就自动获取焦点的bug

    有时候我们在进入activity 的时候,EditText会自动聚焦 有人说搞个宽高 都为0dp的EditText 但是我们搞代码的肯定要从实际层面解决,这样更能说服人 所以只需要在EditText的 ...

  9. dedecmsv5.7 ueditor编辑器上传视频/修改,视频显示空白,解决方案

    dedecmsv5.7 ueditor 在上传视频之后,显示空白.其实是有视频的,就是显示空白.找了资料,记录一下. 解决方案: 找到include下面的ueditor下面的ueditor.all.j ...

  10. a*b高精度数组算法

    #include<stdio.h> #include<string.h> int main() { ]={},b[]={},c[]={},len1=,len2=; ],str2 ...