Cast integer array to void pointer - pthread_create - c++

for passing arguments, pthread requires void pointer. I want to pass two variables, int and long. To save myself some trouble, I will pass two long instead. So this is what I do:
int main(int argc, char *argv[])
{
/*SOCKET INIT*/
pthread_t socketTh;
long data[2] = {ip2l(IP),80};
pthread_create(&socketTh, 0, &serverConnect, (void*)data); //ERROR HERE
while(true) {
/*event loop*/
}
quit_thread(&sockerTh); //just an EXAMPLE! I don't know how to quit threads, I will google it later
return 0;
}
Error:
error: invalid conversion from 'void (*)(void*)' to 'void* (*)(void*)'
But it seems that this is not the correct way to retype long pointer to void pointer. I wonder not of threads Stackoverflow has suggested me didn't help, as well as any Google search. So maybe, try to explain it really slowly, because I'm beginner and I'm still lost in data types.
Thank you.
Update:
I create the unsigned long* in main(). This means this variable will last as long as the program itself.

The error message refers to the third argument. pthread_create wants a pointer to a function that takes a void* and returns void*. Apparently the function serverConnect is a function that takes a void* and returns void.

Related

Trying to get past std::bind compile errors

I've used std::bind before and I think am close on this usage but not quite there and I don't have a clue how to resolve the compile error.
The ultimate goal is a medium-sized array of pointers to a small number of functions, with different parameters in each array element. At this point I just have one function and one table entry. If I can get that right I think I can solve the rest. I want to use std::function so that I can put the varied parameters into the array.
Here's declaration of the one function so far:
static Get *MakeGArrayStatic(void *Subscript, const void **array, unsigned int sizeOfArray);
Here's the declaration of the single pointer that will be typical of the array:
typedef std::tr1::function<Get *(void *, const void**, unsigned int)> GetMaker;
static GetMaker *gm1;
Here's the definition of the pointer:
Get::GetMaker *Get::gm1 = std::tr1::bind(&MakeGArrayStatic, &OutMsg::CurrentSeverity, FacSevTbls::SyslogSeveritiesForMessages, FacSevTbls::NumberOfTrueSeverities);
(Get is a class, CurrentSeverity is an enum, SyslogSeveritiesForMessages is a const char **, and NumberOfTrueSeverities is a size_t.)
The error I am getting (VS 2010) is
error C2440: 'initializing' : cannot convert from 'std::tr1::_Bind<_Result_type,_Ret,_BindN>' to 'Get::GetMaker *'
with
[
_Result_type=Get *,
_Ret=Get *,
_BindN=std::tr1::_Bind3,SyslogEnums::SeverityEnum *,const char **,size_t>
]
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
Can anyone please point out where I am going wrong?
Thank you again to #PlinyTheElder but I think we have left the question "officially" unanswered. Closing the loop, here are the declarations with the first cut at an array of functions:
static Get *MakeGArrayStatic(void *Subscript, const char **array, size_t sizeOfArray);
static Get *MakeGStatic(void *field, size_t sizeOfField);
typedef std::tr1::function<Get *()> GetMaker;
static GetMaker gm[];
and here is the definition of the array so far:
std::tr1::function<Get *()> Get::gm[] = {
std::tr1::bind(&Get::MakeGArrayStatic, &OutMsg::CurrentSeverity, FacSevTbls::SyslogSeveritiesForMessages, FacSevTbls::NumberOfTrueSeverities),
std::tr1::bind(&MakeGStatic, Msg::MessageID, 8) } ;
And here is a trivial example of a call to a function:
Get *g = Get::gm[0]();
Came out better than I had hoped. I had pictured that all of the "little functions" were going to have to have the same signature (like overloads). Compiles cleanly on both target compilers. (Have not tested execution yet, but I am confident.) Thanks again!
Update: yes, it executes.

error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]

Getting error:
error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]
on g++
on the following code:
void* func(void *s)
{
int i = 0;
int self = (int *)s;
printf("Thread Entered: %d\n", self);
sm.lock(self);
// Critical section (Only one thread
// can enter here at a time)
for (i=0; i<MAX; i++)
ans++;
sm.unlock(self);
}
You need to change int self = (int *)s; to int self = *((int *)s); or to int * self = (int *)s;.
You need to think of these as two different things. One is a pointer to memory where the value is stored (int*) and the other is an actual value (int).
Looking at your function declaration void* func(void *s), your s parameter is of type void, this will need to be int if you wish to convert it.
Your data types seem a bit mixed, which just doesn't fly do well in C/C++. Can you clean it? If you are using this function with pthread_create(), as per the documentation with example for this function, try..
// your pthread_create call..
int SOME_INT = 123;
s = pthread_create(&thread_id, &attr, &thread_start, &SOME_INT);
//...and your function
void* func(void *s)
{
int self = (int*) s;
Pointers can be confusing. See if that above code looks similar, in particular to passing the last parameter for pthread_create as a pointer reference. And then try your original code. It might just be that it wasn't passed as a reference.
See what that yields you, else try storing it as a pointer and then converting on use.
void* func(void *s)
{
int *self = s;
sm.lock(*self); // but can give a potential race condition.
In the second line of the function body, I suspect you were trying obtain the value at s (as an int pointer), but you actually cast it directly to an int. That would yield the address in s rather than the value stored there.

pointer to function wont work

I'm trying to learn how to use pointer to function properly. I was supposed to make a pointer to the function strcmp, inside the function check, but the program opens and closes immediately. As far as I understood, the pointer to function is correct on my code returnType (*pointer)(parameters)); So what is going wrong? Thanks in advance.
void check(char *a,char *b,int (*cmp)(const char*,const char*))
{
printf("Testing equality\n");
if(!(*cmp)(a,b)) printf("equals");
else printf("different");
}
int main(void)
{
char s1[80] = "daniel" ,s2[80] = "daniel";
int (*p)(const char*,const char*);
p = strcmp();
check(s1,s2,p);
return 0;
}
This line is incorrect:
p = strcmp();
Here you're calling strcmp with zero arguments, which is invalid. You should have gotten a very clear compiler error about this. For instance, gcc gives me:
error: too few arguments to function ‘int strcmp(const char*, const char*)’
You want to just assign strcmp:
p = strcmp;
Also, you don't need to dereference function pointers to call them, so !(*cmp)(a,b) could be simplified to !cmp(a,b).

Trying to cast integer to void to pass to pthread function by value

I am trying (using pthread_create) to pass a value to the function:
void philosopher(int);
I only need a way to differentiate between each thread. It does not matter which order they run in (clearly, since they are threads), nor even which order they were created in, but they need to contain a least one difference so that I can tell the difference between them. The reason for this is that, in the function, each thread needs to refer to itself as "philosopher 1, philosopher 2,...". The number of philosophers is dynamic (the user passes it as an argument when running the program).
pthread_t threads[philo];
for (int i = 0; i < philo; i++)
pthread_create(&threads[i], NULL, &philosopher, reinterpret_cast<void*>(i));
I get an error from the above code: "invalid conversion from ‘void (*)(int)’ to ‘void* (*)(void*)’ [-fpermissive]. Clearly, I need to pass i by value (because i changes in the for loop). I am stuck at compile time, however, and have only ever been able to have my pthread programs compile when the last value was NULL. I have also tried:
pthread_create(&threads[i], NULL, &philosopher, i);
and
pthread_create(&threads[i], NULL, &philosopher, (void*)i);
both of which produce the same compiler errors.
You're having problem with a different parameter than you think - it's the thread function that's the problem.
It's supposed to take a void * - not an int - and return a void *, so change it to
void* philosopher(void*);
and inside the philosopher function, you cast the parameter back to an int.
(Don't cast the function - that's undefined.)
The error message is pretty clear. You need a function of type void * (void *), and you have a function of type void (int). Fix it:
extern "C"
void * philosopher(void * data)
{
uintptr_t n = reinterpret_cast<uintptr_t>(data);
// ...
return nullptr;
}
(As #Deduplicator mentioned, strictly speaking pthread_create requires that the thread function have C linkage, so in C++ you need to declare it as extern "C".)

C++ typecast error [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
void pointers: difference between C and C++
Hi I have the following function:
void task2(int a)
{
printf(" Task 2 running..\n");
sleep(2);
printf(" Task 2 exiting..\n");
}
thpool_add_work(threadpool, (void*)task2, (void*)a);
int thpool_add_work(thpool_t* tp_p, void *(*function_p)(void*), void* arg_p)
{
// some code here
}
The above code works well with C, but does not compile in C++. I'm getting the following error:
error: invalid conversion from ‘void*’ to ‘void* (*)(void*)’
error: initializing argument 2 of ‘int thpool_add_work(thpool_t*, void* (*)(void*), void*)’
I'm not able to figure out the reason for this error. Any idea why this error crops up when I change the file extension to CPP and compile?
You have to change the signature of task2 to match the type of the thpool_add_work argument:
void* task2(void* a)
The call which creates the thread would become
thpool_add_work(threadpool, task2, &a);
assuming that a is int.
If you need to use the argument of task2, you could do following:
int ia = *(int*)a;
Update to answer the OP comment
thpool_add_work expects a function with void* argument for a reason. In such a way, you can pass any kind of parameter into the thread function, albeit in a type-unsafe way.
You pass the address of the parameter converted to void* as the 3rd argument of thpool_add_work. Afterwards, you cast a pointer to void back to the pointer to your expected parameter type and dereference it to get the value of the parameter. I gave the example for int a above, now how it would look for a float:
void* test3(void* a)
{
float fa = *(float*)a;
.....
return NULL;
}
Try this
thpool_add_work(threadpool, (void* (*)(void*))task2, (void*)a);
C converts void* to any type automatically, C++ does not.
You could improve the code with a typedef
typedef void* (*worker_func_t)(void*);
thpool_add_work(threadpool, (worker_func_t)task2, (void*)a);
int thpool_add_work(thpool_t* tp_p, worker_func_t function_p, void* arg_p)
{
// some code here
}