"invalid conversion from" with pthread_create issue - c++

Any comment is appreciated for the compile error below.
Although my question is similar to other thread: pthread function from a class, I still haven't been able to solve my problem. I am still not that familliar with pointer, and thread programming in C & C++.
Error
../src/Main.cpp: In function ‘int main(int, char**)’:
../src/Main.cpp:22: error: invalid conversion from ‘unsigned int* (*)(void*)’ to ‘void* (*)(void*)’
../src/Main.cpp:22: error: initializing argument 3 of ‘int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)’
make: *** [src/Main.o] Error 1
Main.cpp
#include <process.h>
#include "ThreadInstance.hpp"
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char** argv)
{
pthread_mutex_t mutex;
int ht1;
pthread_t threadId1;
pthread_attr_t attr1;
pthread_mutex_init(&mutex, NULL);
pthread_attr_init(&attr1);
pthread_attr_setdetachstate(&attr1, PTHREAD_CREATE_DETACHED);
ht1 = pthread_create(&threadId1,
&attr1,
&ThreadInstance::ThreadEntryPoint,
//(void *)readThread);
NULL);
unsigned long rc = 0;
rc = pthread_join(ht1, NULL);
return 0;
}
ThreadInstance.hpp
#ifndef _SCENE_CLASSIFY_THREAD_H
#define _SCENE_CLASSIFY_THREAD_H
#ifndef STDCALL
#define STDCALL __attribute__((stdcall))
#endif
using namespace std;
class ThreadInstance
{
public:
ThreadInstance();
ThreadInstance(int camNum);
void startUp();
static unsigned STDCALL* ThreadEntryPoint(void* pThis)
{
//static unsigned __stdcall ThreadEntryPoint(void* pThis) {
ThreadInstance *ptr = (ThreadInstance*) pThis;
ptr->startUp();
//return 1; // Returns error "invalid conversion from ‘int’ to ‘unsigned int*’" when the function is declared as pointer.
// Since returning either 1 or 0,
// compile error still occurs.
// So this return value should not be the cause.
return 0;
}
~ThreadInstance();
};
#endif
Note: Only necessary part is shown

Your ThreadEntryPoint must return void*.
The error indicates the type that is expected, and that is the function pointer type that you are required to use.

The start function returns void* and takes void*. Yours returns unsigned int*.
Change the method to return a pointer to void.

Related

How can i pass a string as parameter for a thread in Windows?

I'm studying threads in c++. I'm using the CreateThread() function from windows.h library:
#include <windows.h>
#include <iostream>
#include <unistd.h>
DWORD WINAPI ThreadFunc(void* data, std::string message) {
std::cout<<message;
return 0;
}
int main() {
std::string saluti="hi";
HANDLE thread = CreateThread(NULL, 0, ThreadFunc, &saluti, 0, NULL);
sleep(5);
}
The error:
error: invalid conversion from 'DWORD (__attribute__((__stdcall__)) *)(void*, std::__cxx11::string) {aka long unsigned int (__attribute__((__stdcall__)) *)(void*, std::__cxx11::basic_string<char>)}' to 'LPTHREAD_START_ROUTINE {aka long unsigned int (__attribute__((__stdcall__)) *)(void*)}' [-fpermissive]
HANDLE thread = CreateThread(NULL, 0, ThreadFunc, &saluti, 0, NULL);
^
how can i pass a std::string to a thread function?
The thread start routine needs to have the signature:
DWORD __stdcall ThreadFunc(LPVOID lpThreadParameter);
So, you need to cast the void* into the pointer type which you sent into the function:
DWORD WINAPI ThreadFunc(LPVOID lpThreadParameter) {
std::string& message = *static_cast<std::string*>(lpThreadParameter);
std::cout<<message;
return 0;
}
Just note that the string must not be destroyed while the thread is using it.

Windows C++ Wrap dll into class Error: incompatible with parameter and non-standard syntax

I have a working example in single file with its spapidllm64.h but wanna split into separate files for easier coding. I have tried to reduce it into a minimal version as follows:
// spapidll.h
#define SPDLLCALL __stdcall
typedef void (SPDLLCALL *LoginReplyAddr)(char *user_id, long ret_code, char *ret_msg);
typedef void (SPDLLCALL *p_SPAPI_RegisterLoginReply)(LoginReplyAddr addr);
typedef int (SPDLLCALL *p_SPAPI_Login)();
//main.cpp
void SPDLLCALL LoginReply(char *user_id, long ret_code, char *ret_msg);
p_SPAPI_RegisterLoginReply SPAPI_RegisterLoginReply;
p_SPAPI_Login SPAPI_Login;
int main(void)
{
HINSTANCE hInst = LoadLibrary("spapidllm64.dll");
SPAPI_RegisterLoginReply = (p_SPAPI_RegisterLoginReply)GetProcAddress(hInst, "SPAPI_RegisterLoginReply");
SPAPI_RegisterLoginReply(LoginReply);
SPAPI_Login = (p_SPAPI_Login)GetProcAddress(hInst, "SPAPI_Login");
int rc = SPAPI_Login();
printf("\nSPAPI_Login: %d\n", rc);
Sleep(3000);
FreeLibrary(hInst);
return 0;
}
void SPDLLCALL LoginReply(char *user_id, long ret_code, char *ret_msg)
{
printf("\nLoginReply[%s]: Ret code: %d, Ret msg: %s",user_id, ret_code, (ret_code == 0)?"OK":ret_msg);
}
now I want to put those codes into a class like this:
// test.h
class ApiTester
{
public:
HINSTANCE hInst;
ApiTester(void){
hInst = LoadLibrary("spapidllm64.dll");
}
~ApiTester(void){
FreeLibrary(hInst);
}
void RegisterDLL();
int Login();
void SPDLLCALL LoginReply(char *user_id, long ret_code, char *ret_msg);
void SPDLLCALL ConnectingReply(long host_type, long con_status);
p_SPAPI_RegisterLoginReply SPAPI_RegisterLoginReply;
p_SPAPI_RegisterConnectingReply SPAPI_RegisterConnectingReply;
p_SPAPI_Login SPAPI_Login;
};
// test.c
#include "tester.h"
void ApiTester::RegisterDLL()
{
SPAPI_RegisterLoginReply = (p_SPAPI_RegisterLoginReply)GetProcAddress(hInst, "SPAPI_RegisterLoginReply");
SPAPI_RegisterLoginReply(LoginReply); // Error E0167 C3867
SPAPI_Login = (p_SPAPI_Login)GetProcAddress(hInst, "SPAPI_Login");
}
int ApiTester::Login()
{
int rc = SPAPI_Login();
printf("\nSPAPI_Login: %d\n", rc);
}
void SPDLLCALL ApiTester::LoginReply(char *user_id, long ret_code, char *ret_msg){
printf("\nLoginReply[%s]: Ret code: %d, Ret msg: %s",user_id, ret_code, (ret_code == 0)?"OK":ret_msg);
}
Then Windows VS C++ shows this error:
Error (active) E0167 argument of type "void (__stdcall ApiTester::*)(char *user_id, long ret_code, char *ret_msg)" is incompatible with parameter of type "LoginReplyAddr"
Error C3867 'ApiTester::LoginReply': non-standard syntax; use '&' to create a pointer to member
Not sure why it works in single file but couldn't work in this way. I thought it should be straight-forward(Hopefully, there is no typo). I'd be appreciate if there is any help.
typedef void (SPDLLCALL *LoginReplyAddr)(char *user_id, long ret_code, char *ret_msg);
typedef void (SPDLLCALL *p_SPAPI_RegisterLoginReply)(LoginReplyAddr addr);
According to the definition above, LoginReplyAddr is a function pointer, not a class member function pointer.
void ApiTester::RegisterDLL()
{
SPAPI_RegisterLoginReply = (p_SPAPI_RegisterLoginReply)GetProcAddress(hInst, "SPAPI_RegisterLoginReply");
SPAPI_RegisterLoginReply(LoginReply); // Error E0167 C3867
...
In this code, LoginReply is class member function pointer.
void (__stdcall ApiTester::*)(char *user_id ...
I guess that is the problem.
If you want to use the class member function as a callback, you also have to pass the 'this' of the class.
Or you can use the static member function.
The link below could help you.
Using a C++ class member function as a C callback function

Cannot convert parameter 1 from 'int (__thiscall A::* *)(void)' to 'int (__cdecl *)(void)'

I am getting this error while running this code. Please look in to my code and assist me.
#include "stdafx.h"
#include <iostream>
class A
{
public:
void PrintTwoNumbers(int (*numberSource)(void))
{
int val1= numberSource();
}
int overNineThousand(void)
{
return (rand()%1000) + 9001;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
int (A::*fptr) (void) = &A::overNineThousand;
int (A::*fptr1) (void);
fptr1 = &A::overNineThousand;
A a;
a.PrintTwoNumbers(&fptr); //-> how to pass here
getchar();
return 0;
}
I am fed up by searching this online, and nobody is giving a perfect solution for this.Can anybody edit this code as working code and help me?
The expected argument is a (non-member) function pointer. You instead pass a (pointer to a) pointer to member function. (Pointers to) Pointers to member functions are not convertible to pointers to (non-member) functions.
Probably the simplest solution is to fix the function argument to be of correct type, pass the implicit object argument and don't take the address of your member function pointer when you call.
void PrintTwoNumbers(int (A::*numberSource) ())
{
int val1= (this->*numberSource)();
}
a.PrintTwoNumbers(fptr);

Perform function with time interval SDL/c++

I want a function to be called every third second. In objective-c I would do like this:
NSTimer timer = [NSTimer timerWithInterval:3 sel:#selector(my_function)...];
How do I do this with SDL and c++? I've tried this:
SDL_TimerID myTimer = SDL_AddTimer(3,my_function(), NULL);
But I just get an error which says: No matching function for call to SDL_AddTimer.
What is wrong?
The first parameter should be 3000 since the documentation lists the units as milliseconds.
edit:
If the prototype doesn't match I get:
~/sdl$ g++ example.cpp -lSDL example.cpp: In function ‘int main(int,
char**)’: example.cpp:13:59: error: invalid conversion from ‘void
(*)()’ to ‘SDL_NewTimerCallback {aka unsigned int (*)(unsigned int,
void*)}’ [-fpermissive] /usr/include/SDL/SDL_timer.h:109:37: error:
initializing argument 2 of ‘_SDL_TimerID* SDL_AddTimer(Uint32,
SDL_NewTimerCallback, void*)’ [-fpermissive]
Which shows that the function prototype has to be:
unsigned int my_function(unsigned int, void * )
This compiles:
#include <SDL/SDL.h>
unsigned int my_function(unsigned int interval, void * param)
{
return interval; // repeat the timer
}
int main(int argc, char ** argv)
{
SDL_TimerID myTimer = SDL_AddTimer(3000, my_function, NULL);
return 0;
}

CppCMS tutorial: Linking template statically error (controller issue)

From http://cppcms.com/wikipp/en/page/cppcms_1x_tut_hello_templates#The.controller
I've places below codes on bottom of hello.cpp:
virtual void main(std::string /*url*/)
{
content::message c;
c.text=">>>Hello<<<";
render("message",c);
}
When running g++ hello.cpp my_skin.cpp -o hello -lcppcms -lbooster, got error:
hello.cpp:44:38: error: ‘virtual’ outside class declaration
hello.cpp:44:38: error: ‘::main’ must return ‘int’
hello.cpp:44:14: warning: first argument of ‘int main(std::string)’ should be ‘int’ [-Wmain]
hello.cpp:44:14: warning: ‘int main(std::string)’ takes only zero or two arguments [-Wmain]
hello.cpp: In function ‘int main(std::string)’:
hello.cpp:44:38: error: declaration of C function ‘int main(std::string)’ conflicts with
hello.cpp:27:5: error: previous declaration ‘int main(int, char**)’ here
hello.cpp: In function ‘int main(std::string)’:
hello.cpp:48:23: error: ‘render’ was not declared in this scope
Do I missed something
The error messages are telling you everything you need to know.
virtual can only be used in a class. Your main method is not in a class.
The main method must return an int. Yours is returning void.
You have two main methods, one that is main(std::string) and one that is main(int, char**)
Your render method must have a function prototype above the main method or the entire method needs to me moved.
So this would be more appropriate:
void render(std::string, std::string) // or whatever
{
// do something
}
int main(int argc, char** argv)
{
render("string", c);
return 0;
}
Your hello.cpp should look like below:
#include <cppcms/application.h>
#include <cppcms/applications_pool.h>
#include <cppcms/service.h>
#include <cppcms/http_response.h>
#include <iostream>
#include "content.h"
class hello : public cppcms::application {
public:
hello(cppcms::service &srv) : cppcms::application(srv) {}
virtual void main(std::string url);
};
void hello::main(std::string /*url*/){
content::message cc;
cc.text=">>>Hello<<<";
render("message", cc);
}
int main(int argc,char ** argv){
try {
cppcms::service srv(argc,argv);
srv.applications_pool().mount(cppcms::applications_factory<hello>());
srv.run();
}
catch(std::exception const &e) {
std::cerr<<e.what()<<std::endl;
}
}