I'm currently writing some code that utilizes boost.python
. I want to convert an std::vector<unsigned char>
to a Python bytes-like object, (I just need to expose the data to Python). The converter I wrote looks like this
#include <Python.h>
#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <stdio.h>
#include <iostream>
#include <vector>
struct vector_to_bytes{
static PyObject* convert(std::vector<unsigned char> const &vec){
std::printf("Converter Called\n");
const unsigned char * p=&vec[0];
for (char c:vec){
std::printf("%x",c);
}
std::printf("\n");
return PyMemoryView_FromMemory((char *)p,vec.size(),PyBUF_READ);
}
};
However, when I try to print the bytes from Python by using memoryview.tobytes().hex()
and compare it with the output from the C++ code, some information is lost.
So the output from C++ looks like this (data truncated)
ffffffffffffffd8ffffffffffffffe00104a4649460110010100ffffffffffffffdb043064565466567768a10aa99a14efc1017141818171416161a1d251f1a1b231c
And from Python (data truncated)
ffd8ffe000104a46494600010100000100010000ffdb00430006040506050406060506070706080a100a0a09090a140e0f0c1017141818171416161a1d251f1a1b231c
So all the ff
s from C++ were replaced with a single ff
, yet both results somehow start to line up at 10171418
, which doesn't make any sense to me.
I feel something may have gone wrong with the typecasting from const unsigned char *
to char *
, but I don't know how to fix it.
System: MacOS 10.13.6
Python 3.7.0
Boost 1.69.0
C++ 14
EDIT
The above section only shows the part that I thought was relevant. The full code is here:
#include <Python.h>
#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/overloads.hpp>
#include <string>
#include <fstream>
#include <opencv2/opencv.hpp>
#include <vector>
class VideoStream {
protected:
cv::Mat frame;
cv::Size resolution;
int quality;
int id;
void captureFrame() {
this->caps >> frame;
};
virtual void processFrame() {
cv::resize(frame, frame, resolution);
}
public:
cv::VideoCapture caps;
VideoStream(int i, int rx, int ry, int quality) {
this->resolution = cv::Size(rx, ry);
#if defined(__linux__)
this->caps = cv::VideoCapture(i+1,cv::CAP_V4L);
#else
this->caps = cv::VideoCapture(i);
#endif
this->id = i;
this->quality=quality;
if (!caps.isOpened())
std::printf("Video capture for cam %d failed", i);
};
~VideoStream() {
caps.release();
}
cv::Mat getFrame() {
captureFrame();
processFrame();
return this->frame;
}
std::vector<unsigned char> getCompressedFrame() {
std::vector<uchar> buf;
captureFrame();
processFrame();
cv::imencode(".jpg", frame, buf, std::vector<int>{
cv::IMWRITE_JPEG_QUALITY, quality,
cv::IMWRITE_JPEG_OPTIMIZE, 1,
});
return buf;
}
void setResolution(int width) {
this->resolution = cv::Size(width, width/1.5);
}
int getHeight(){
return resolution.height;
}
int getWidth(){
return resolution.width;
}
void setQuality(int q){
this->quality=q;
}
int getQuality(){
return quality;
}
int getId(){
return id;
}
};
struct vector_to_bytes{
static PyObject* convert(std::vector<unsigned char> const &vec){
std::printf("Converter Called\n");
const unsigned char * p=&vec[0];
for (char c:vec){
std::printf("%x",c);
}
std::printf("\n");
return PyMemoryView_FromMemory((char *)p,vec.size(),PyBUF_READ);
}
};
BOOST_PYTHON_MODULE(video_frame){
using namespace boost::python;
to_python_converter<std::vector<unsigned char>,vector_to_bytes>();
class_<VideoStream>("VideoStream",init<int,int,int,int>())
.def("getCompressedFrame",&VideoStream::getCompressedFrame)
.def("setQuality",&VideoStream::setQuality,args("quality"))
.def("setResolution",&VideoStream::setResolution,args("width"))
.def("getWidth",&VideoStream::getWidth)
.def("getHeight",&VideoStream::getHeight)
.def("getQuality",&VideoStream::getQuality)
.def("getId",&VideoStream::getId)
;
}