最通俗易懂的封装C/C++代码为Python模块【附OpenCV

您所在的位置:网站首页 代码接口如何快速移植文件 最通俗易懂的封装C/C++代码为Python模块【附OpenCV

最通俗易懂的封装C/C++代码为Python模块【附OpenCV

2024-07-10 11:14| 来源: 网络整理| 查看: 265

本文教程参考自微软官方文档:创建适用于 Python 的 C++ 扩展

前言背景

看了好多人写的方法,最后发现只有在微软官网文档上找到的方法最可行。封装C++代码主流方法都是封装成dll文件调用。

首先我们必须明白为什么我们能在Python里面调用C++的方法,因为我们主流使用的Python解释器是C写的,为了区别开用其他语言实现的python,为此我们通常叫它Cpython,可以理解为:用C实现的python。

使用 C/C++编写的模块常用于扩展 Python 解释器的功能和启用对低级别操作系统功能的访问。 主要有以下 3 种类型的模块:

加速器模块:Python 是一种解释型语言,某些代码段可使用 C++ 进行编写来提高性能。包装器模块:向 Python 代码公开现有 C/C++ 接口,或公开易于通过 Python 使用的更“Python 化”的 API。低级别系统访问模块:用于访问 CPython 运行时的较低级别功能、操作系统或基础硬件。 环境准备

VS环境:VS2019/2017/2015 Python环境:原生的Python3.6(非Anaconda)

实现最基础的C2Python接口

先创建一个空的C++项目

第一步:创建完成后,在新项目中创建 C++ 文件,选择“添加” > “新建项”,选择“C++ 文件”,将其命名为 module.cpp。

第二步:右键单击“解决方案资源管理器”中的 C++ 项目,然后选择“属性”。

第三步:在显示的“属性页”对话框顶部,将“配置”设置为“所有配置”,并将“平台”设置为“x64”(根据你的项目需求选择平台) 在这里插入图片描述 第四步:如下表配置属性: 在这里插入图片描述 在这里插入图片描述 第六步:生成,按照上面配置无误不会出现报错

第七步:编写C++函数: 实现一个对自增300的函数C_func

#include #include #include //我们即将在python里面调用这个函数 PyObject* C_Func(PyObject*, PyObject* o) { //o是python对象,Cpython接口利用Pyobject进行数据交互 double x = PyFloat_AsDouble(o); //把Pyobject转换为double,因为在python以浮点数的形式传进来的 double result = x + 300; return PyFloat_FromDouble(result);//然后把C++的double转回PyObject } static PyMethodDef superfastcode_methods[] = { { "Py_Func", (PyCFunction)C_Func, METH_O, nullptr }, //Py_Func 是在python里面引用的名字 { nullptr, nullptr, 0, nullptr } }; static PyModuleDef superfastcode_module = { PyModuleDef_HEAD_INIT, "C2Python", // Module name to use with Python import statements 模块的名字 "Module description", // Module description 模块信息描述 0, superfastcode_methods // Structure that defines the methods of the module }; PyMODINIT_FUNC PyInit_C2Python() { return PyModule_Create(&superfastcode_module); }

打开生成目录,找到以pyd结尾的文件,这是编译出来的二进制文件 在这里插入图片描述 第八步:在同个目录下,创建一个python文件:xxxx.py 代码如下:

import C2Python a=C2Python.Py_Func(100) #Py_Func 这个函数名字是在C++的PyMethodDef里面写的 print(a)

输出:400.0 至此,调用成功。

C++的Opencv的Mat类型转Python的numpy数组

我们知道在C++里面的opencv定义了一个独一无二的Mat类,和opencv-python里面直接使用numpy数组是有差异的。Cpython里面提供的接口可以交互的数据类型:int,float,bytes。所以,我们进行数据交互只能用bytes类型。网上不少文章的方法会出现内存读取错误,如果我们按照元数据作为字节数据转换很有可能会出现问题。我们可以从网络图片数据传输方法得到灵感,使用Base64编码进行数据交互。

第一步:头文件声明

创建一个Trans.hpp,代码如下:

#include #include #include #include #include #include using namespace cv; using namespace std; Mat Base2Mat(string& base64_data); string Mat2Base64(const Mat& img, string imgType); char* string2char(string code); 第二步:写C++传输类

我们创建一个新的Cpp文件:Trans.cpp,用于辅助数据传输(保证当前项目已经进行正确的opencv环境配置)

#include "Trans.hpp" string base64Decode(const char* Data, int DataByte) { //解码表 const char DecodeTable[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, // '+' 0, 0, 0, 63, // '/' 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9' 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z' 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z' }; //返回值 string strDecode; int nValue; int i = 0; while (i 2]; strEncode += EncodeTable[((Tmp[1] & 0x03) 2]; strEncode += EncodeTable[((Tmp[1] & 0x03) 4)]; strEncode += EncodeTable[((Tmp[2] & 0x0F)


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3