SDL2 Thread not working inside class - c++

I am trying to create a input handler using multi threading with the SDL2 Library; however, when I try to put a thread in a class it won't compile and gives me this error...
error: cannot convert 'inputHandlerClass::getInput' from type 'int (inputHandlerClass::)(void*)' to type 'SDL_ThreadFunction {aka int (*)(void*)}'
I'm pretty sure that its the way I am passing the function name (fn) to the SDL_CreateThread function.
This is the source.cpp file
#include <iostream>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#include <SDL_thread.h>
#include <SDL_mixer.h>
#include "..\include\gameClass.hpp"
#include "..\include\inputHandlerClass.hpp"
int main(int argc, char *argv[]){
inputHandlerClass inputHandler;
inputHandler.startThread();
std::cout << "hello world";
return 0;
}
This is the inputHandlerClass.hpp
#include <SDL_thread.h>
#include <iostream>
class inputHandlerClass{
private:
SDL_Thread *thread;
int threadReturnValue;
public:
inputHandlerClass();
int getInput(void *ptr);
void startThread();
};
//Default Constructor
inputHandlerClass::inputHandlerClass(){
this->thread = SDL_CreateThread(getInput, "inputThread", this);
}
int inputHandlerClass::getInput(void *ptr){
int cnt;
for(cnt= 0; cnt < 10; ++cnt){
std::cout << "counter: " << cnt << std::endl;
SDL_Delay(50);
}
return cnt;
}
void inputHandlerClass::startThread(){
SDL_WaitThread(this->thread, &this->threadReturnValue);
}

SDL_CreateThread expects a pointer to a regular function with int(void *ptr) signature as first parameter, however you are providing a non-static member function (not even a pointer because member functions aren't getting implicitly converted to a pointer). You should redeclare getInput as static. this pointer will be available as ptr.

Related

How do I access member variables from a repeating timer callback

Using the RPI Pico SDK, I have three files.
I want to use a callback function and access private members of a class.
The callback function is in an SDK and I can not modify it.
How do I do this?
/////// test.h
bool main_loop_timer_callback(struct repeating_timer *t);
class MyClass {
private:
static int count;
struct repeating_timer main_loop_timer;
public:
MyClass();
friend bool main_loop_timer_callback(struct repeating_timer *t);
};
//////// test.cc
#include <iostream>
#include "pico/stdlib.h"
#include "test.h"
using namespace std;
bool main_loop_timer_callback(struct repeating_timer *t) {
MyClass::count++;
cout << "callback " << MyClass::count << endl;
return true;
}
MyClass::MyClass() {
add_repeating_timer_us(-50000,
main_loop_timer_callback,
NULL,
&main_loop_timer);
count = 0;
};
/////// test-main.cc
#include "pico/stdlib.h"
#include "test.h"
using namespace std;
int main() {
MyClass test;
stdio_init_all();
}
The Pi Pico repeating_timer API allows you to pass a user_data argument when adding a timer (the third parameter to add_repeating_timer_us).
This value is later returned in the user_data member of the struct repeating_timer passed to your callback.
This can be anything you want, e.g. in your case, a pointer to MyClass, so long as you cast it to and from void *.

How access class functions with <future> library?

I'm trying to make a program with #include <future> library.
When I try to access a header function, I get an error.
no instance of overloaded function "async" matches the argument list -- argument types are: (std::launch, int ()) [line 16, 14]
a pointer to a bound function may only be used to call the function
[line 16, 37]
main.cpp:
#include "TEST.h"
#include <future>
#include <iostream>
using namespace std;
using namespace Class;
FNH f;
int main(){
auto fn = async(launch::async, f.selam);
}
TEST.h:
#pragma once
#include <iostream>
using namespace std;
namespace Class{
class FNH{
public:
int selam(){
cout << "selam";
return 1;
}
};
}
I'm a beginner at coding so I really don't know how to fix it or if it's possible.
You can pass a member function pointer and the instance of the class it will be called on:
#include <future>
#include <iostream>
namespace Class {
class FNH {
public:
int selam(){
std::cout << "selam";
return 1;
}
int selam_2(int a, int b){
std::cout << "selam "<< a << " " << b;
return 1;
}
};
}
int main(){
Class::FNH f;
// Member Function Pointer
auto fn = std::async(std::launch::async, &Class::FNH::selam, f);
// Member Function Pointer with arguments
auto fn2 = std::async(std::launch::async, &Class::FNH::selam_2, f, 1, 2);
}
Put the method call in a lambda
#include <future>
#include <iostream>
namespace Class{
class FNH {
public:
int selam(){
std::cout << "selam";
return 1;
}
};
}
int main(){
Class::FNH f;
auto fn = std::async(std::launch::async, [&f]{ return f.selam(); });
}

C++ compiling error

I have a compiling error in C++ using classes. I have worked with classes before and have never encountered this error. I have tried adding static before the method ImprtData but that only prompted more errors.
error: invalid use of non-static member function bank.ImprtData;
here is my .cpp
#include "componets.h"
User::User() {
std::cout << "loaded" << std::endl;
}
void User::ImprtData() {
std::cout << "loaded.\n";
}
and here is my .h
#include <sstream>
#include <fstream>
#include <vector>
#include <iostream>
#include <string>
class User {
public:
User();
void write();
void launch_main_menu();
void login();
void ImprtData();
private:
void deposit();
void withdrawl();
std::string account_name;
int account_pin;
float account_balance;
std::string account_user_name;
};
and finally my main
#include "componets.h"
int main() {
std::cout << "Welcome to Bank 111.\n";
User bank;
bank.ImprtData;
return 0;
}
This is essentially a simple typo. Replace
bank.ImprtData;
with
bank.ImprtData();
to call the function. The expression bank.ImprtData is confusing the compiler since it's interpreting it as the address of a function, and issues a diagnostic since the function is not static.
bank.ImprtData; should be bank.ImprtData();

Reference to object with std::async

I have a small solution in visual studio 2012. The solution consists of two projects (Scanner and TestApp), Scanner is a dll and TestApp is a small application using the dll.
I would like a function in the dll to run in a thread and to report its result back via a queue to the TestApp.
To test this I wrote a minimal application, but depending on how I launch the thread I get different results and I would like to understand why.
The Scanner.h file looks like this:
#pragma once
#include <iostream>
#include <string>
#include <stdint.h>
#include <atomic>
#include <future>
#include <thread>
#include "version.h"
#include "threadsafe_queue.h"
#include "capture_data.h"
#include "process_data.h"
#ifdef SCANNER_EXPORTS
#define SCANNER_API __declspec(dllexport)
#else
#define SCANNER_API __declspec(dllimport)
#endif
class Scanner
{
public:
static SCANNER_API void run();
static SCANNER_API void stop();
};
Scanner.cpp:
#include "stdafx.h"
#include "Scanner.h"
std::vector<std::future<int>> my_futures;
void Scanner::run()
{
CaptureData capture_data(1234);
auto t = std::async(std::launch::async, &CaptureData::get_data, capture_data);
my_futures.push_back(std::move(t));
}
void Scanner::stop()
{
for(int n=0; n<my_futures.size(); n++) {
auto e = std::move(my_futures.back());
e.get();
my_futures.pop_back();
}
}
The class CaptureData is defined in capture_data.h and capture_data.cpp.
capture_data.h:
#pragma once
#include <atomic>
#include <thread>
#include "iq_data.h"
#include "threadsafe_queue.h"
class CaptureData
{
public:
CaptureData(double freq_start);
void configure();
void get_data();
private:
double m_test;
};
capture_data.cpp
#include "stdafx.h"
#include "capture_data.h"
#include "Scanner.h"
ThreadsafeQueue<int> g_queue_1;
SCANNER_API ThreadsafeQueue<int> g_queue_2;
CaptureData::CaptureData(double test)
: m_test(test) {}
void CaptureData::get_data()
{
cout << "1: " << m_test << std::endl;
Sleep(5000);
cout << "2: " << m_test << std::endl;
g_queue_2.push(3);
cout << "Capture has now pushed data" << std::endl;
}
And finally the TestApp.cpp:
#include "stdafx.h"
#include "tchar.h"
#include <stdint.h>
#include <string>
#include "Scanner.h"
SCANNER_API extern ThreadsafeQueue<int> g_queue_2;
int _tmain(int argc, _TCHAR* argv[])
{
Scanner scanner;
scanner.run();
cout << "TestApp waiting for data..." << std::endl;
int data;
g_queue_2.wait_and_pop(data);
cout << "TestApp got data: " << data << std::endl;
scanner.stop();
return 0;
}
In Scanner.cpp I have tried to launch the thread in two different ways, the first way:
auto t = std::async(std::launch::async, &CaptureData::get_data, capture_data);
Second way is with a reference to the object "capture_data":
auto t = std::async(std::launch::async, &CaptureData::get_data, &capture_data);
The first way seems to work as I intended the application to work and I get the following printouts in my terminal:
TestApp waiting for data...
1: 1234
2: 1234
Capture has now pushed data
TestApp got data: 3
Press any key to continue...
If I use the second way I get:
TestApp waiting for data...
1: 6.95166e-310
2: 6.95166e-310
Capture has now pushed data
TestApp got data: 3
Press any key to continue...
So, what I do not understand is why the variable "m_test" get messed up in the second case.
I would very much appreciate if anyone could shed a light on this.
/M
In the following code:
void Scanner::run()
{
CaptureData capture_data(1234);
auto t = std::async(std::launch::async, &CaptureData::get_data, capture_data);
my_futures.push_back(std::move(t));
}
capture_data is a local variable that goes out of scope and gets destroyed when the function returns. If you pass a pointer to that variable into async that pointer becomes a dangling pointer causing undefined behaviour. That does not happen if you pass it by value, as you do in the above snippet.
You are trying to pass a pointer to a stack allocated object. This object is destructed at the end of the Scanner::run() method. Thus, the pointer is now pointing to invalid memory when the async function runs.
The first method works, because the capture_data variable is move constructed when it is passed to the function, therefore it still retains it's structure.
I recommend using lambda functions than passing the raw member function:
void Scanner::run()
{
CaptureData capture_data(1234);
auto t = std::async(std::launch::async, [capture=std::move(capture_data)]() { capture.get_data(); });
my_futures.emplace_back(t);
}
Even better is to construct the object inside the lambda function:
void Scanner::run()
{
auto t = std::async(std::launch::async, []() {
CaptureData capture_data(1234);
capture_data.get_data();
});
my_futures.emplace_back(t);
}

How to refer to the pointer **environ in a user-defined namespace's member function?

#include <iostream>
namespace A {
void func();
}
void A::func()
{
extern char **environ;
std::cout << environ[0] << std::endl;
}
int main()
{
A::func();
return 0;
}
Like the code above, I just want to use the system-defined pointer **environ in A::func(), but g++ always says:
undefined reference to `A::environ'
How can I use the system-defined variable environ correctly?
Add
#include <unistd.h>
and environ must be in global scope.
So the code would look like this:
#include <iostream>
#include <unistd.h>
extern char **environ;
namespace A {
void func();
}
void A::func()
{
std::cout << environ[0] << std::endl;
}
int main()
{
A::func();
return 0;
}
You just need to declare environ at global scope, which is of course where it is defined, rather than within your function.
If you want to be a little cleaner about it and avoid unnecessary use of global variables, you can declare main this way:
int main(int argc, char* argv[], char* envp[])
Then simply pass envp to your function. It will work the same as the global.