I am trying to make a basic game in c++ using the SFML library. For this game, I want a thread
drawing at a fixed rate and another thread checking for input as often as possible. The first problem I encountered was that the SFML library does not allow for window to be active on multiple threads. A simple fix for this was found by just deactivating the window in the main thread. The next problem that I have not yet found a fix for is that I cannot seem to check for input on my main thread (In this scenario).
This code is very unreliable. I can get two different error messages, or an infinite loop. What should happen is an infinite loop that can be closed with the escape key, and if you press d it prints a message.
The library I am using is libsfml-dev
My compile arguments are as follows: g++ test.cpp -pthread -lsfml-graphics -lsfml-window -lsfml-system
#include <iostream>
#include <stdio.h>
#include <pthread.h>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
sf::RenderWindow window(sf::VideoMode(800, 800), "");
using namespace std;
void *func(void *threadid) {
cout << "New thread." << endl;
while (window.isOpen()) {
// In the actual implementation, this would be replaced with draw methods
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) {
window.close();
}
}
pthread_exit(NULL);
}
int main() {
// Needed so that window is only active on a single thread
window.setActive(false);
// Create new thread
pthread_t threads[1];
int val;
val = pthread_create(&threads[0], NULL, func, (void *)1);
cout << "Main thread." << endl;
while (window.isOpen()) {
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) {
cout << "D button pressed." << endl;
}
}
return 0;
}
Error Number 1
PS: XInitThreads doesn't help
Error Number 2
Looks like an error from my X server
Related
I'm new to C++ and am trying to have two threads run:
i) Thread that keeps looping until an atomic bool is flipped.
ii) A thread that polls for input from keyboard and flips the atomic bool.
I seem to be unable to get std::cin.get() to react to an input unless it is assigned its' own thread (like below). Why? Would it not then be set from the parent main thread?
#include <iostream>
#include <iomanip> // To set decimal places.
#include <thread> //std::thread
#include <atomic> //for atomic boolean shared between threads.
#include <math.h>
#define USE_MATH_DEFINES //For PI
std::atomic<bool> keepRunning(false); //set to false to avoid compiler optimising away.
void loop(){
int t = 1;
while(!keepRunning.load(std::memory_order_acquire)) //lower cost than directly polling atomic bool?
{
//Write sine wave output to console.
std::cout << std::setprecision(3) << sin(M_PI * 2 * t/100) << std::endl;
(t<101)? t++ : t = 1;
}
}
//This works, as opposed to stopping in main.
void countSafe(){
int j = 1;
while (j<1E7)
{
j++;
}
keepRunning.store(true, std::memory_order_release); //ends the loop thread.
}
int main(){
std::thread first (loop); //start the loop thread
std::thread second (countSafe); //start the countSafe thread. Without this it doesn't work.
//Why does polling for std::cin.get() here not work?
//std::cin.get(); //wait for key press. puts in buffer..?
//keepRunning.store(true, std::memory_order_release); //Set stop to true.
second.join(); //pause to join.
first.join(); //pause to join
return 0;
}
I'm not quite sure what your problem is, but use of cin.get() might be part of it. Let's simplify with this code:
#include <iostream>
using namespace std;
int main(int, char **) {
cout << "Type something: ";
cin.get();
cout << "Done.\n";
}
Try that code and run it. Then type a single character. Chances are that the code won't recognize it. And you can type all you want until you hit return.
This is complicated, but your program doesn't actually receive the characters until you hit return unless you play other games. Like I said, it's complicated.
It's possible behavior is different on Windows, but this is the behavior on Mac and Linux.
So is it "not working" because you tried typing a space but you really need to use Return?
I've been searching for a while, and I don't achieve to find any way to get the input keys of my keyboard, to use them in my program...
Context : I'm starting on robotics, and C++, and I'd simply like to command a motor.
The idea is that "if I press the up arrow, the motor turns, if I press the down arrow, the motor stops" and that's it, no need to validate something or anything like that...
I am with raspbian, through VNC (controlling from my real computer), and the actual code is executed in the terminal.
I'll see later on to make that more complex.
I went through 20 or more pages and didn't find anything helpful... Isn't there an easy way to do something that seems so basically useful?
Some spoke about conio library, but apparently it's outdated, curses/ncurses took its place,but I didn't achieve to find/have anything working...
http://www.cplusplus.com/forum/general/74211/
Create a function to check for key press in unix using ncurses
Capture characters from standard input without waiting for enter to be pressed
This is apparently C code, and not C++, moreover, I don't really understand that...
How to detect key presses in a Linux C GUI program without prompting the user?
This, maybe? But it makes no sense to me (beginner in C++)
How can I get the keyboard state in Linux?
here they speak of "allegro", but apparently, it don't work on the PI 45 yet... and no idea how to install that anyway
http://www.cplusplus.com/forum/general/47357/
Does someone knows a simple little code that I can copy-past to do that, or any way? I'm quite shocked to not have something similar to windows C++ programming where it seems so simple
I mean something like "Keyboard.GetKeyStates(Key)"
I'll continue my research anyway, but please, help !
EDIT :
Apparently, the library SDL (SDL2) can help me do this...
I tried to implement it, it doesn't give any result...
Here is the code I got up to now (I deleted a good part that is useless in here), basically, it's a copy-past from internet SDL official web page :
#include <iostream>
#include <wiringPi.h> //Raspberry pi GPIO Library
#include <cstdio>
#include <csignal>
#include <ctime>
#include <chrono> //library for counting time
#include <thread> //for "this thread sleep"
#include <SDL2/SDL.h> //for getting the keyboard buttons events
bool RUNNING = true; // global flag used to exit from the main loop
/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
GPIO Pins definition
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
int SPser = 13, SPclk = 19, SPrclk = 26; //Define the output pins used
int Optocoupler = 17; //define the input pins used
/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
SDL definition
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
//void PrintKeyInfo( SDL_KeyboardEvent *key );
//void PrintModifiers( SDLMod mod );
//SOME CODE
// Callback handler if CTRL-C signal is detected
void my_handler(int s) {
std::cout << "Detected CTRL-C signal no. " << s << '\n';
RUNNING = false;
}
//###################################################################################
int main(int argc, char *args[]) {
// Initialize wiringPi and allow the use of BCM pin numbering
wiringPiSetupGpio();
//Initialize SDL
if (SDL_Init(SDL_INIT_EVENTS) != 0) {
SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
return 1;
}
else
{
SDL_Log("SDL initialized");
}
SDL_Event event;
// Register a callback function to be called if the user presses CTRL-C
std::signal(SIGINT, my_handler);
while(RUNNING)
{
while( SDL_PollEvent( &event ) )
{
std::cout << "SDL While \n" << '\n';
//When the user presses a key
switch( event.type )
{
case SDL_KEYDOWN:
std::cout << "Key press detected \n" << '\n';
//printf( "Key press detected\n" );
break;
case SDL_KEYUP:
std::cout << "Key release detected \n" << '\n';
//printf( "Key release detected\n" );
break;
default:
break;
}
}
//std::cout << "Works??" << '\n';
/*for( i = 0; i <= 15; i++ )
{
//std::cout << "data input i =" << i << '\n';
if (i==0){
//std::cout << "if array " << i << '\n';
DataArr[i]=1;
DataArr[15]=0;
}
else{
j=i-1;
DataArr[j]=0;
DataArr[i]=1;
//std::cout << "in else i" << i << " and j " << j << '\n';
}
SendData(DataArr);
}*/
}
std::cout << "Program ended ...\n";
}
As I followed "dumbly" the tutorial, this should work, but the while loop is never entered as the "std::cout << "SDL While \n" << '\n';" is never shown...
But, as it achieve to compile, I guess the SDL library was installed correctly and things work...
When executing the code, it writes "SDL initialized", then, nothing... pressing keys do nothing
I'm still not sure how to check if the library is installed correctly, but when I type in de command prompt "sudo apt-get install libsdl2-dev", it shows a few lines and says "0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded"
If you are on linux, you should use termios to stop the buffering
#include <termios.h>
void set_no_buffer()
{
struct termios term;
tcgetattr(0, &term);
term.c_lflag &= ~ICANON;
tcsetattr(0, TCSANOW, &term);
}
and then getchar() to get a character without entering
I'm developing an app that should freeze all input, both keyboard and mouse, for a period of time. I've tried using XGrabKeyboard, but I cannot revert its effect using XUngrabKeyboard, it does nothing.
Here's a minimal example you can easily compile:
#include <iostream>
#include <thread>
#include <chrono>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xresource.h>
#include <X11/cursorfont.h>
int main(int argc, char *argv[])
{
Display * dpy = nullptr;
dpy = XOpenDisplay(0);
if(!dpy)
{
std::cerr << "Error" << std::endl;
return 1;
}
std::cerr << "Grabbing..." << std::endl;
XGrabKeyboard(dpy, DefaultRootWindow(dpy), false, GrabModeAsync, GrabModeAsync, CurrentTime);
std::cerr << "Waiting 2 secs, you shouldn't be able to type anything" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
std::cerr << "Ungrabbing..." << std::endl;
XUngrabKeyboard(dpy, CurrentTime);
std::cerr << "Try to type now" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
}
You can see that you cannot write anything anymore. I've tried clicking on the terminal, in case the focus is lost or anything, to no avail. Once the program finishes the keyboard is released.
Not sure if it has something to do with the parameters in the XGrabKeyboard call, I've tried modifying them (Sync vs Async, etc). But there's no difference.
Adding an XSync(dpy, true); (*) after XUngrabKeyboard makes the code behave in the way you expected. So possibly you have to process all the events you grabbed before the event queue resumes?
(*): don't actually do this, this is just to demonstrate that the problem is with the queued events
Also works:
XUngrabKeyboard(dpy, CurrentTime);
XEvent foo;
while (XPending(dpy)) XNextEvent(dpy, &foo);
Update - also works:
XFlush(dpy);
So... the problem is that the ungrab was not actually sent?
I am using opencv library to obtain video from the built-in webcam. The following code works perfectly well when i put camera logic code into the main function, but it doesn't when i put it into separate thread. The task1() thread stops at cv::VideoCapture capture(0). Meanwhile both task2() and the main thread are executing correctly.
Could someone explain me why opencv logic doesn't work when put into separate thread?
My code:
#include <iostream>
#include <string.h>
#include <thread>
#include <unistd.h>
#include <opencv2/opencv.hpp>
using namespace std;
void task1 (){
cout<<"1st thread ";
cv::Mat frame;
cv::VideoCapture capture(0);
if ( capture.isOpened() == false )
{
cout<<"Failed to open camera";
}
cv::namedWindow("Test OpenCV",1);
while ( true ){
capture >> frame;
cv::imshow("Test OpenCV", frame );
int key = cv::waitKey(1);
if ( key == 27 )
break;
}
}
void task2 (){
int n = 0;
while (1){
cout<<"2nd thread "<<n<<"\n";
sleep(3);
n++;
}
}
int main(int argc, const char * argv[]) {
// insert code here...
cout << "Hello, World!\n";
thread t1(task1);
thread t2(task2);
//t1.join();
//t2.join();
int n = 0;
while (1){
cout<<"main thread "<<n<<"\n";
sleep(1);
n++;
}
return 0;
}
Your code runs as it should for me (without any modifications) and I get the live feed through the task1 thread (using OpenCV 2.4.5).
I added -std=gnu++0x flag for compiler support (otherwise g++ throws an error).
g++ -std=gnu++0x opencv_thread.cpp -o opencv_thread `pkg-config --cflags --libs opencv`
Check my console output here. I added a cout << "1st thread "<< endl; within the while loop in task1.
I think the issue might be specific to some opencv versions as I have seen similar issues in an older version (don't remember which one) and boost threads.
Can you give details about the version you used?. Also try it with 2.4.5.
I am using MSVC with Visual Studio 2013. This is the code I am compiling:
#include <iostream>
using namespace std;
void crash()
{
cout << "crash?" << endl;
system("PAUSE");
}
int main(int argc, char *argv[])
{
atexit(crash);
//while(true);
return 0;
}
The way it is right now - it works like a charm. I start the program, it goes inside the crash function, pauses, I press a key and it closes normally. All cool. However, if I uncomment the while loop and use the X button on the console to close it, I get a crash inside the endl function. I was able to determine that the crash is caused by _Ostr.widen()
This is the implementation of the endl function, provided by MSVC:
template<class _Elem,
class _Traits> inline
basic_ostream<_Elem, _Traits>&
__CLRCALL_OR_CDECL endl(basic_ostream<_Elem, _Traits>& _Ostr)
{ // insert newline and flush stream
_Ostr.put(_Ostr.widen('\n'));
_Ostr.flush();
return (_Ostr);
}
Using Ctrl+C to terminate the program causes the same effect. How can I fix this?
Seems like my suspicions turned out to be true. I modified the code like so:
#include <iostream>
using namespace std;
#include <Windows.h>
void crash()
{
printf("%i\n", GetCurrentThreadId());
system("PAUSE");
}
int main()
{
printf("%i\n", GetCurrentThreadId());
atexit(crash);
//while(true);
return 0;
}
When the program exists normally both printf()s display identical thread IDs, however when I press Ctrl+C or the X button the thread IDs are different, which explains the crash and makes a lot of sense when you think about it. Thus, here is a small example how this issue can be tackled:
#include <iostream>
#include <conio.h>
using namespace std;
#include <Windows.h>
volatile bool wantClose = false;
void OnExit()
{
cout << GetCurrentThreadId() << endl;
system("PAUSE");
}
BOOL WINAPI OnConsoleClose(DWORD dwCtrlType)
{
wantClose = true; // set a flag that the console wants us to close
ExitThread(0); // kill this thread immediately so it doesn't make the console stuck
return FALSE;
}
int main()
{
cout << GetCurrentThreadId() << endl;
SetConsoleCtrlHandler(OnConsoleClose, TRUE); // handle close requests from the console
atexit(OnExit);
while(!wantClose); // at some point in our code we will have to check whether the console wants us to close down
return 0;
}
Please note: The usage of system("PAUSE") and busy waiting are only for the sake of keeping the example simple. I do not advise their usage in real code.