I am trying to use low level IO (Read) to read in standard input for a command. After getting that command I try to pass it into execvp so that it can carry out the command but it is not working. I think the problem is I am not sure how to pass it into execvp properly. It worked before with command line arguments but I cant get standard input working.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <string.h>
int main(int argc, char* argv[])
{
int r;
char b1[4096];
char command[4096];
r = read(STDIN_FILENO, b1, 4096);
memcpy(command, b1, r);
command[r] = '\0';
//printf("%s\n", command);
char* progname = command;
//char* progname = argv[1];
pid_t pid;
if ((pid = fork()) < 0) perror("fork");
else if (pid == 0) { // child process
if (execvp(progname, argv + 1) == -1) {
perror("execvp");
return EXIT_FAILURE;
} // if
} // if
else {
fprintf(stderr, "Please specify the name of the program to exec as a command line argument\n");
return EXIT_FAILURE;
} // if
} // main
I'm trying to draw a point on the window by using QImage, and update the position of this point as fast as possible(less than 1ms every update). I've wrote the code below and run it, but the result is it's too slow(about 50ms every update). I searched the bottleneck and found the cause of this slowness is calling QWidget.update() takes too long. So I figured out as long as using Widget.update() it won't be faster. So I think I need another way. Is there any faster way to do this? All of the codes and the result are the following.
result:
qimageBehaviorForStackOverflowQuestion.pro
######################################################################
# Automatically generated by qmake (3.1) Wed Mar 29 15:18:09 2017
######################################################################
TEMPLATE = app
TARGET = qimageBehaviorForStackOverflowQuestion
INCLUDEPATH += .
QT += widgets
# Input
HEADERS += qimageBehaviorForStackOverflowQuestion.h
SOURCES += qimageBehaviorForStackOverflowQuestion.cpp
qimageBehaviorForStackOverflowQuestion.h
#include <iostream>
#include <QApplication>
#include <QWidget>
#include <QTimer>
#include <QPainter>
#include <QPushButton>
#include <QImage>
#include <QTime>
class MyWidget : public QWidget {
Q_OBJECT
private:
QImage *image;
int px, py;
uchar d[100*100*4];
QTimer *timer;
QTime time;
public:
MyWidget();
void paintEvent(QPaintEvent * event);
public slots:
void doPaint();
};
qimageBehaviorForStackOverflowQuestion.cpp
#include "qimageBehaviorForStackOverflowQuestion.h"
int my_counter = 0;
MyWidget::MyWidget() : QWidget(0), px(0), py(0){
image = new QImage(d, 100, 100, QImage::Format_ARGB32);
for(int cnt = 0, a, r, g, b; cnt < 100*100*4;){
a = 255; //alpha
r = 0; //red
g = 0; //green
b = 0; //blue
d[cnt] = b; cnt++;
d[cnt] = g; cnt++;
d[cnt] = r; cnt++;
d[cnt] = a; cnt++;
}
// connect QTimer.timeout to my doPaint method
timer = new QTimer();
connect(timer, SIGNAL(timeout()), this, SLOT(doPaint()));
timer->start(1);
};
void MyWidget::doPaint(){
// manipulate the positions of the points
if(px < 100){
int cnt = 0, b = 255, g = 255, r = 255, a = 255;
d[4 * px + cnt] = b; cnt++;
d[4 * px + cnt] = g; cnt++;
d[4 * px + cnt] = r; cnt++;
d[4 * px + cnt] = a; cnt++;
px++;
}
// update the window
update();
};
void MyWidget::paintEvent(QPaintEvent * event){
QPainter painter(this);
painter.drawImage(0, 0, *image);
}
int main(int argc, char *argv[]){
QApplication app(argc, argv);
MyWidget *widget = new MyWidget();
widget->show();
return app.exec();
}
After googling couple of hours, I found more faster way. It becomes incredibly very fast(once 20FPS is now about 500FPS).What I'm using now is QGraphicsView Framework and QPixmap and QGraphicsPixmapItem. However I don't know this is the right or efficient way, if it isn't please correct me. And if you know there is more faster way please let me know. Any way I show you the code. I hope it could help someone who fight same problem.
qgraphicsSceneExample.h
#include <iostream>
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QTimer>
#include <QPainter>
#include <QPushButton>
#include <QImage>
#include <QTime>
#include <QStyleOptionGraphicsItem>
#include <QWidget>
#include <QPixmap>
#include <QGraphicsPixmapItem>
class MyView : public QGraphicsView {
Q_OBJECT
private:
QGraphicsScene *scene;
QImage *image;
QPixmap *pixmap;
QGraphicsPixmapItem *gpixmapItem;
int px, py;
uchar d[100*100*4];
QTimer *timer;
QTime time;
public:
MyView();
//void paintEvent(QPaintEvent * event);
public slots:
void doPaint();
};
qgraphicsSceneExample.cpp
#include "qgraphicsSceneExample.h"
int my_counter = 0;
MyView::MyView() : px(0), py(0){
image = new QImage(d, 100, 100, QImage::Format_ARGB32);
for(int cnt = 0, a, r, g, b; cnt < 100*100*4;){
a = 255; //alpha
r = 0; //red
g = 0; //green
b = 0; //blue
d[cnt] = b; cnt++;
d[cnt] = g; cnt++;
d[cnt] = r; cnt++;
d[cnt] = a; cnt++;
}
// connect QTimer.timeout to my doPaint method
timer = new QTimer();
connect(timer, SIGNAL(timeout()), this, SLOT(doPaint()));
scene = new QGraphicsScene(0);
pixmap = new QPixmap(QPixmap::fromImage(*image));
gpixmapItem = scene->addPixmap(*pixmap);
this->setScene(scene);
timer->start(1);
};
void MyView::doPaint(){
// manipulate the positions of the points
if(px < 100){
int cnt = 0, b = 255, g = 255, r = 255, a = 255;
d[4 * px + cnt] = b; cnt++;
d[4 * px + cnt] = g; cnt++;
d[4 * px + cnt] = r; cnt++;
d[4 * px + cnt] = a; cnt++;
px++;
}
pixmap = new QPixmap(QPixmap::fromImage(*image));
gpixmapItem->setPixmap(*pixmap);
std::cout << my_counter++ << "\n";
};
int main(int argc, char *argv[]){
QApplication app(argc, argv);
MyView *myView = new MyView();
myView->show();
return app.exec();
}
Consider changing the incrementation of Px to more than +1, +5 for example. that will reduce the calls of doPaint() function by 5 times. and will speed up the drawing. Because your problem is that you are updating the drawing a lot, 100 times.
P.S : you should also stop the timer to stop calling doPaint() function when the drawing is finished. because it is called every 1ms. since timer.start(1) will emit timeout() signal every 1ms.
Edit:
Consider also changing the timeout that is very light (an update every 1ms <=> 1000 FPS).
who can tell me ? I use directshow and wia but don't find the method
Why don't you use the OpenCV?
main.cpp
int main(int argc, char** argv) {
CvCapture* capture = cvCaptureFromCAM(0);
int index = 0;
while(cvGrabFrame(capture)) {
/*Get webcam image!*/
IplImage *camImg = cvRetrieveFrame(capture);
/*Save the image to the disk!*/
string fileName = "tmp/" + int2str(index) + ".jpg";
cvSaveImage(fileName.c_str(), screenShotImg);
index++;
int key = cvWaitKey(10);
if(key == 27) {
break;
}
}
cvReleaseCapture(&capture);
return 0;
}
TypeConvert.cpp
#include "TypeConvert.h"
#include <iostream>
#include <sstream>
string int2str(int &num) {
string emptyStr;
stringstream ss(emptyStr);
ss << num;
return ss.str();
}
I have a class ClientWindow. I have created several instances of it and appended the their pointers to a a list. If i try to show any of the windows however, I get "Segmentation fault (core dumped)" I keep the list of windows in a class called controller.
Here is my controller header file:
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include "clientwindow.h"
class Controller
{
public:
Controller();
void createClients(int num);
void showWindows();
private:
QList<ClientWindow*> clWList;
int size;
};
#endif // CONTROLLER_H
this is the cpp file:
#include "controller.h"
Controller::Controller()
{
}
void Controller::createClients(int num)
{
size = num;
for(int i = 0; i < size; i++)
{
ClientWindow cw;
clWList.append(&cw);
}
}
void Controller::showWindows()
{
for(int i = 0; i < size; i++)
{
ClientWindow* cw = clWList.at(0);
cw->show();
}
}
this is my main:
#include <QtGui/QApplication>
#include "clientwindow.h"
#include "controller.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// ClientWindow w;
// w.show();
QString temp = argv[1];
bool ok;
int tempI = temp.toInt(&ok, 10);
Controller c;
c.createClients(tempI);
c.showWindows();
return a.exec();
}
This is where it goes wrong:
for(int i = 0; i < size; i++)
{
ClientWindow cw;
clWList.append(&cw);
}
A local variable cw is created on the stack in each iteration. It is deallocated at the end of each iteration. Meaning the data is gone. So you end up storing pointers pointing to junk.
Calling a member function of a junk typically results in crash. :) Do this instead:
for(int i = 0; i < size; i++)
{
ClientWindow * cw = new ClientWindow();
clWList.append(cw);
}
You'll have to go through the list and delete the objects after you are done with them.
I am trying to port my program from Windows to Linux. The windows program uses Window CryptoAPI and linux is using libmcrypt.
Here is the Windows code:
#include <windows.h>
#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <exception>
using namespace std;
class CryptError:public exception{
public:
CryptError(){}
};
#define CHECK_RET(x) if(x == FALSE) {retval = GetLastError(); throw CryptError();};
LONG Decrypt(const string &key, std::vector<BYTE> &data){
LONG retval = 0;
try{
HCRYPTPROV hCrypt;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
CHECK_RET(CryptAcquireContext(&hCrypt, NULL, NULL, PROV_RSA_FULL, 0));
CHECK_RET(CryptCreateHash(hCrypt, CALG_MD5, 0, 0, &hHash));
CHECK_RET(CryptHashData(hHash, reinterpret_cast<const BYTE *>(key.c_str()), key.size(), 0));
CHECK_RET(CryptDeriveKey(hCrypt, CALG_RC2, hHash, MAKELPARAM(CRYPT_EXPORTABLE, 80), &hKey));
BYTE tempVal[200];
DWORD len = 200;
CryptGetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, tempVal, &len, 0);
len = 200;
CryptGetKeyParam(hKey, KP_MODE, tempVal, &len, 0);
len = 200;
CryptExportKey(hKey, NULL, PLAINTEXTKEYBLOB, 0, tempVal, &len);
len = 200;
CryptGetKeyParam(hKey, KP_IV, tempVal, &len, 0);
DWORD count = data.size();
CHECK_RET(CryptDecrypt(hKey, 0, TRUE, 0, &(data[0]), &count));
data.resize(count);
}catch(CryptError &e){
}
return retval;
}
int main(void){
BYTE data[9] = {0xdc,0x3d,0x96,0x23,0x29,0xdd,0x1b,0x2f, 0};
vector<BYTE> vData(data, data + 8);
Decrypt("PNEMAIL", vData);
cerr << "vData: ";
int len = vData.size();
for(int i = 0; i < len; i++){
if(i > 0)
cerr << ',';
cerr << hex << setw(2) << setfill('0') << (int)(vData[i]);
}
cerr << endl;
return 0;
}
When the program is run, it returns:
vData: 42,46,30,41,43,34,31
The Q&D linux version looks like this:
#include <mcrypt.h>
#include <iostream>
#include <iomanip>
#include <string>
#include <openssl/md5.h>
#include <stdint.h>
#include <stdexcept>
#include <vector>
#include <valarray>
#include <memory.h>
using namespace std;
class MCrypt{
private:
MCRYPT mcrypt;
public:
MCrypt(char *algorithm, char* algorithm_directory, char *mode, char* mode_directory){
mcrypt = mcrypt_module_open(algorithm, algorithm_directory, mode, mode_directory);
if(mcrypt == MCRYPT_FAILED)
throw runtime_error("MCrypt init failed");
}
int init(void *key, int lenofkey, void *IV){
return mcrypt_generic_init(mcrypt, key, lenofkey, IV);
}
int enc_get_iv_size(){
return mcrypt_enc_get_iv_size(mcrypt);
}
int deinit(){
return mcrypt_generic_deinit(mcrypt);
}
int decrypt(void *data, int len){
mdecrypt_generic(mcrypt, data, len);
}
~MCrypt(){
deinit();
mcrypt_module_close(mcrypt);
}
};
#ifdef DEBUG
void inline printArrayFunc(const char *start, const uint8_t *data, int len){
// DEBUG: print value of $key1
cerr << start;
for(int i = 0; i < len; i++){
if(i > 0)
cerr << ',';
cerr << hex << setw(2) << setfill('0') << (int)(data[i]);
}
cerr << endl;
}
#define printArray(start, data, len) printArrayFunc(start, data, len)
#else
#define printArray(start, data, len)
#endif
int main(void){
uint8_t data[8] = {0xdc,0x3d,0x96,0x23,0x29,0xdd,0x1b,0x2f};
const char *sKey1 = "PNEMAIL";
const int key1Len = 7;
uint8_t *dataPtr = &(data[0]);
uint8_t key1[17];
key1[16] = 0;
// Hash sKey1
MD5(reinterpret_cast<const unsigned char *>(sKey1), key1Len, key1);
MCrypt mcrypt(MCRYPT_RC2, NULL, MCRYPT_CBC, NULL);
vector<uint8_t> iv(mcrypt.enc_get_iv_size(), 0);
// Use the first 80-bits of key1
mcrypt.init(key1, 10, &(iv[0]));
mcrypt.decrypt(dataPtr, 8);
printArray("vData: ", dataPtr, 8);
return 0;
}
When the program is run, it returns:
vData: 4d,3d,82,71,88,d2,d5,4b
I've check that both programs are using the same data.
CryptDeriveKey creates a key 07,f1,e2,ea,d4,c8,79,74,03,a6 (according to CryptExportKey), the same as the first 10 bytes of the md5 generated in Linux (which I shorten to match the requested 80-bit key).
Neither are using a salt on the algorithm (or at least are not reporting as such)
They are both using an 8-byte IV of {0,0,0,0,0,0,0,0}
They are both using the RC2 algorithm
They are both using CBC mode
I cannot figure out why they are returning different data. Any assistance would be greatly appreciated.