python编译安装没有c扩展_pybind11—python C/C++扩展编译
前言
在之前的pybind11系列实践中,开发流程大致是这样的:
第一步: 首先在C/C++ IDE中编写C/C++函数,然后采用pybind11封装为python可调用的包装函数, 之后采用C/C++编译器生成.pyd文件
image.png
第二步:将生成的.pyd文件复制到python工程中,之后作为python module import导入使用
image.png
存在的问题
不同操作系统下直接调用生成的pyd可能会出错,不能跨平台调用
在上述过程中,pyd动态链接库的生成是在本地PC上,但是如果想在不同的操作系统、硬件平台上调用之前生成的pyd,显然是会出错的。比如在windows上编译生成了一个python扩展.pyd, 但是Ubuntu系统或者树莓派上想调用这个python扩展显然就不行了。
为了使得C/C++创建的python扩展可以跨平台使用,那么最简单的办法就是直接发布源码, 然后在该操作系统、硬件平台上编译生成python扩展。
本节内容利用python setuptools 方式实现
开发环境
windows 10 64bit
Anaconda3, with python 3.7
pybind11
C/C++ python扩展的实现
Project1
创建一个简单的工程, 之后创建一个package,取名demo1:
image.png
创建如下文件:
__init__.py 创建包默认生成的
example.cpp C++代码
setup.py 用于编译C++代码,生成C/C++ python扩展
test.py 测试
在Visual Studio中测试通过之后,将C/C++源码文件添加的python工程目录中,然后创建一个setup.py文件,编写如下代码:
在Extension中设置C/C++源码文件、第三方库的依赖文件,由于本工程采用pybind11进行C++ 与python接口的封装,因此需要包含pybind11库的头文件,pybind11库是header-only,因此无需包含lib。
setup.py
from setuptools import setup
from setuptools import Extension
example_module = Extension(name='numpy_demo', # 模块名称
sources=['example.cpp'], # 源码
include_dirs=[r'D:\Anaconda3_2\include', # 依赖的第三方库的头文件
r'D:\pybind11-master\include']
)
setup(ext_modules=[example_module])
example.cpp
#include
#include
#include
#include
namespace py = pybind11;
/*
https://blog.csdn.net/u013701860/article/details/86313781
https://blog.csdn.net/u011021773/article/details/83188012
*/
py::array_t calcMul(py::array_t& input1, py::array_t& input2) {
// read inputs arrays buffer_info
py::buffer_info buf1 = input1.request();
py::buffer_info buf2 = input2.request();
if (buf1.size != buf2.size)
{
throw std::runtime_error("Input shapes must match");
}
// allocate the output buffer
py::array_t result = py::array_t(buf1.size);
}
class Matrix
{
public:
Matrix() {};
Matrix(int rows, int cols) {
this->m_rows = rows;
this->m_cols = cols;
m_data = new float[rows*cols];
}
~Matrix() {};
private:
int m_rows;
int m_cols;
float* m_data;
public:
float* data() { return m_data; };
int rows() { return m_rows; };
int cols() { return m_cols; };
};
void save_2d_numpy_array(py::array_t a, std::string file_name) {
std::ofstream out;
out.open(file_name, std::ios::out);
std::cout << a.ndim() << std::endl;
for (int i = 0; i < a.ndim(); i++)
{
std::cout << a.shape()[i] << std::endl;
}
for (int i = 0; i < a.shape()[0]; i++)
{
for (int j = 0; j < a.shape()[1]; j++)
{
if (j == a.shape()[1]-1)
{
//访问读取,索引 numpy.ndarray 中的元素
out << a.at(i, j)<< std::endl;
}
else {
out << a.at(i, j) << " ";
}
}
}
}
//
//py::array_t rgb_to_gray(py::array_t& a) {
//
// py::array_t dst = py::array_t(a.shape()[0] * a.shape()[1]);
// //指针访问numpy矩阵
// unsigned char* p = (unsigned char*)dst.ptr();
//
// for (int i = 0; i < a.shape()[0]; i++)
// {
// for (int j = 0; j < a.shape()[1]; j++)
// {
// auto var = a.data(i, j);
// auto R = var[0];
// auto G = var[1];
// auto B = var[2];
//
// //RGB to gray
// auto gray = (R * 30 + G * 59 + B * 11 + 50) / 100;
//
// std::cout << static_cast(R) << " " << static_cast(G) << " " << static_cast(B)<< std::endl;
//
// //p[i*a.shape()[1] + j] = static_cast(gray);
//
// }
// }
//}
PYBIND11_MODULE(numpy_demo, m) {
m.doc() = "Simple numpy demo";
py::class_(m,"Matrix",py::buffer_protocol())
.def_buffer([](Matrix& mm)->py::buffer_info {
return py::buffer_info(
mm.data(), //Pointer to buffer, 数据指针
sizeof(float), //Size of one scalar, 每个元素大小(byte)
py::format_descriptor::format(), //python struct-style foramt descriptor
2, //Number of dims, 维度
{mm.rows(), mm.cols()}, //strides (in bytes)
{sizeof(float) * mm.cols(),sizeof(float)}
);
});
m.def("save_2d_numpy_array", &save_2d_numpy_array);
//m.def("rgb_to_gray", &rgb_to_gray);
}
在pycharm底下,打开终端:
image.png
将路径切换到setup.py所在目录,然后执行命令:
image.png
生成python扩展库:
image.png
image.png
最后,会发现工程中增加了一些新的目录和文件,其中xxxx.pyd就是生成的python扩展库。
image.png
python扩展库测试
test.py
import demo1.numpy_demo as numpy_demo
import numpy as np
help(numpy_demo)
mat1 = numpy_demo.save_2d_numpy_array(np.zeros(shape=[10,10], dtype=np.float32), r'./data.dat')
print(mat1)
image.png
image.png
image.png
Project2 opencv工程
第一个工程比较简单,没有包含和依赖第三方库,一般C/C++工程中,往往包含和依赖许多第三方库,本工程以opencv库为例,实现C/C++ python扩展模块的编译。
image.png
编写setup.py
from setuptools import Extension
from setuptools import setup
__version__ = '0.0.1'
# 扩展模块
ext_module = Extension(
# 模块名称
name='cv_demo1',
# 源码
sources=[r'mat_warper.cpp', r'main.cpp'],
# 包含头文件
include_dirs=[r'D:\Anaconda3_2\include',
r'D:\opencv-4.1.0\opencv\build\include',
r'D:\pybind11-master\include'
],
# 库目录
library_dirs=[r'D:\opencv-4.1.0\opencv\build\x64\vc15\lib'],
# 链接库文件
libraries=[r'opencv_world410'],
language='c++'
)
setup(
name='cv_demo1',
version=__version__,
author_email='xxxx@qq.com',
description='A simaple demo',
ext_modules=[ext_module],
install_requires=['numpy']
)
编译python扩展库:
在终端执行命令
image.png
image.png
python代码测试:
test.py
import demo2.cv_demo1 as cv_demo
import numpy as np
import cv2
import matplotlib.pyplot as plt
help(cv_demo)
image = cv2.imread(r'F:\lena\lena_gray.jpg', cv2.IMREAD_GRAYSCALE)
# canny
img_canny = cv_demo.test_gray_canny(image)
plt.figure('canny')
plt.imshow(img_canny, cmap=plt.gray())
# pyramid
imgs_pyramid = cv_demo.test_pyramid_image(image)
plt.figure('pyramid')
for i in range(1, len(imgs_pyramid)):
plt.subplot(2, 2, i)
plt.imshow(imgs_pyramid[i])
# rgb to gray
plt.figure('rgb->gray')
img_gray = cv_demo.test_rgb_to_gray(cv2.imread(r'F:\lena\lena_rgb.jpg'))
plt.imshow(img_gray)
plt.show()
python测试结果:
canny边缘检测
image.png
Gaussian图像金字塔
image.png
图像RGB转Gray
image.png
C++源码:
main.cpp
#include
#include
#include
#include
#include
#include
#include"mat_warper.h"
namespace py = pybind11;
py::array_t test_rgb_to_gray(py::array_t& input) {
cv::Mat img_rgb = numpy_uint8_3c_to_cv_mat(input);
cv::Mat dst;
cv::cvtColor(img_rgb, dst, cv::COLOR_RGB2GRAY);
return cv_mat_uint8_1c_to_numpy(dst);
}
py::array_t test_gray_canny(py::array_t& input) {
cv::Mat src = numpy_uint8_1c_to_cv_mat(input);
cv::Mat dst;
cv::Canny(src, dst, 30, 60);
return cv_mat_uint8_1c_to_numpy(dst);
}
/*
@return Python list
*/
py::list test_pyramid_image(py::array_t& input) {
cv::Mat src = numpy_uint8_1c_to_cv_mat(input);
std::vector<:mat> dst;
cv::buildPyramid(src, dst, 4);
py::list out;
for (int i = 0; i < dst.size(); i++)
{
out.append<:array_t char>>(cv_mat_uint8_1c_to_numpy(dst.at(i)));
}
return out;
}
PYBIND11_MODULE(cv_demo1, m) {
m.doc() = "Simple opencv demo";
m.def("test_rgb_to_gray", &test_rgb_to_gray);
m.def("test_gray_canny", &test_gray_canny);
m.def("test_pyramid_image", &test_pyramid_image);
}
mat_warper.h
#ifndef MAT_WARPER_H_
#include
#include
#include
namespace py = pybind11;
cv::Mat numpy_uint8_1c_to_cv_mat(py::array_t& input);
cv::Mat numpy_uint8_3c_to_cv_mat(py::array_t& input);
py::array_t cv_mat_uint8_1c_to_numpy(cv::Mat & input);
py::array_t cv_mat_uint8_3c_to_numpy(cv::Mat & input);
#endif // !MAT_WARPER_H_
mat_warper.cpp
#include"mat_warper.h"
#include
/*
Python->C++ Mat
*/
cv::Mat numpy_uint8_1c_to_cv_mat(py::array_t& input) {
if (input.ndim() != 2)
throw std::runtime_error("1-channel image must be 2 dims ");
py::buffer_info buf = input.request();
cv::Mat mat(buf.shape[0], buf.shape[1], CV_8UC1, (unsigned char*)buf.ptr);
return mat;
}
cv::Mat numpy_uint8_3c_to_cv_mat(py::array_t& input) {
if (input.ndim() != 3)
throw std::runtime_error("3-channel image must be 3 dims ");
py::buffer_info buf = input.request();
cv::Mat mat(buf.shape[0], buf.shape[1], CV_8UC3, (unsigned char*)buf.ptr);
return mat;
}
/*
C++ Mat ->numpy
*/
py::array_t cv_mat_uint8_1c_to_numpy(cv::Mat& input) {
py::array_t dst = py::array_t({ input.rows,input.cols }, input.data);
return dst;
}
py::array_t cv_mat_uint8_3c_to_numpy(cv::Mat& input) {
py::array_t dst = py::array_t({ input.rows,input.cols,3}, input.data);
return dst;
}
//PYBIND11_MODULE(cv_mat_warper, m) {
//
// m.doc() = "OpenCV Mat -> Numpy.ndarray warper";
//
// m.def("numpy_uint8_1c_to_cv_mat", &numpy_uint8_1c_to_cv_mat);
// m.def("numpy_uint8_1c_to_cv_mat", &numpy_uint8_1c_to_cv_mat);
//
//
//}
python编译安装没有c扩展_pybind11—python C/C++扩展编译相关推荐
- python详细安装教程linux-Linux环境下Python的安装方法
本文主要介绍linux下采用源码包的方式进行python的安装. 一.下载python源码包 打开ubuntu下的shell终端,通过wget命令下载python源码包,如下图所示: 将python- ...
- python pip安装第三方库老是报错_#python pip 安装dlib一直失败?#python安装dlib错误...
#python pip 安装dlib一直失败?#python安装dlib错误 python dlib 教程2020-10-11 07:52:36人已围观 ubuntu里面怎么安装dlib 下面是在ub ...
- python怎样安装词云_在python中怎样安装词云-女性时尚流行美容健康娱乐mv-ida网...
女性时尚流行美容健康娱乐mv-ida网 mvida时尚娱乐网 首页 美容 护肤 化妆技巧 发型 服饰 健康 情感 美体 美食 娱乐 明星八卦 首页 > 高级搜索 腾讯qq 云 词典正式发布无需下 ...
- 学python需要安装什么软件-学武汉Python培训课程需要安装什么软件?分享这10款...
工欲善其事必先利其器.初学者在学Python的时候,往往会因为没有好用的软件工具,走了很多弯路.因此一些好用的软件工具,可以极大地提高开发效率,那么学武汉Python培训课程需要安装什么软件呢?本文千 ...
- python怎么安装pandas模块-如何在Python 3中安装pandas包和使用数据结构
介绍 Python pandas包用于数据操作和分析,旨在让您以更直观的方式处理标记或关系数据. 基于numpy软件包构建,pandas包括标签,描述性索引,在处理常见数据格式和丢失数据方面特别强大. ...
- win7下python的安装与配置_Win7下Python与Tensorflow-CPU版开发环境的安装与配置过程...
以此文记录Python与Tensorflow及其开发环境的安装与配置过程,以备以后参考. 1 硬件与系统条件 Win7 64位系统,显卡为NVIDIA GeforeGT 635M 2 安装策略 a.由 ...
- python需要安装的库_使用python学习【机器学习】需要安装的库~
---------------------------------------------------------------------------------------------------- ...
- 【2023版】超详细Python+Pycharm安装保姆级教程,Python环境配置和使用指南,看完这一篇就够了
这两年被Python初学小白问到最多的问题就是,该用什么代码编辑工具? 说实话,我个人是用Jupyter Notebook最多,主要是经常做数据可视化,方便些. 但对于初学者来说,PyCharm仍是不 ...
- 怎么找到python的安装目录_怎么查看python的安装目录呢
方法一.sys.executable可以获得python解析器的路径,它的上一级即为它的安装路径 >>>import sys >>>path = sys.execu ...
- python手机安装教程视频_《python安装教程有没有?最好是视频的》 python搭建环境视频教程...
学习python有什么好的视频教程 自python需要花点时间跟心思,而且要整套的教程去学习,这样你自己识思维上才不乱. 链接: https://pan.baidu.com/s/1TXjBVcnaC3 ...
最新文章
- html和css占前端的多少比例,【CSS】前端怎么实现像chrome浏览器的百分比缩放同样的效果?...
- 虚拟机登服务器,用虚拟机登录云服务器
- Blockquotes,引用,html里面,经常用到的一个!
- mongodb for java_【MongoDB for Java】Java操作MongoDB
- 关于window.showModalDialog()返回值的学习
- Java自定义拦截器详细教程
- 2021年上半年软考真题网络工程师真题及答案解析
- 方方格子access_有哪些好用能提高工作效率的 Excel 插件(或 Office 办公插件)值得推荐?...
- PySide2 QCheckBox控件应用
- mysql中tab键作用_MySQL小技巧-mysql命令 tab键数据表名、字段名补全功能
- CentOS7 Docker 端口映射
- python中shape的解释
- 基于Qt的局域网即时通讯软件
- 【1.7k行代码优秀课设】基于stm32f4xx粤嵌GEC-M4的按键密码锁、呼吸灯、蜂鸣器音乐、超声波测距及倒车雷达、温湿度检测、光敏电阻自动灯光调节、USART串口控制系统
- Tomcat8+Redis集群解决会话共享
- OpenStack-Placement组件部署详解(T版)
- 手机sim卡插到电脑上网_你知道吗?关于手机SIM卡的一些事
- 惊了!原来Go语言也有隐式转型
- 基于freeSWITCH的sip协议利用WebRTC 实现实时视频聊天
- 在美国创业公司工作经验分享
热门文章
- 如何在spring框架中解决多数据源的问题[转]
- 通过WDS功能扩大无线网范围
- php框架运行流程,thinkphp项目执行流程介绍
- 点击场景中的物件无法定位到Hierarchy
- java中JFrame.setSize,Java JFrame .setSize(x, y) not working?
- 计算机组成原理学习-哈工大《计算机组成原理》第一章
- 国考报名显示服务器繁忙,公益性岗位考试内容-面试:牢记服务初心,让海关面试作答更具温度...
- c语言mooc第五周作业,中国大学MOOC 浙江大学《程序设计入门——C语言》第5周:循环控制 测验与作业...
- 大脑计算机马云,人类和计算机谁更聪明?马云和马斯克在2019世界人工智能大会机智交锋...
- LintCode—链表倒数第n个节点(166)