Reputation: 510
I'm using a library provided by my professor for a class assignment so I can't reveal too much of my code. Here's part of the API:
typedef void (*thread_startfunc_t) (void*);
int thread_libinit(thread_startfunc_t func, void *arg);
int thread_create(thread_startfunc_t func, void *arg);
thread_libinit initializes the thread library. A user program should call
thread_libinit exactly once (before calling any other thread functions).
thread_libinit creates and runs the first thread. This first thread is
initialized to call the function pointed to by func with the single
argument arg. Note that a successful call to thread_libinit will not
return to the calling function. Instead, control transfers to func, and
the function that calls thread_libinit will never execute again.
thread_create is used to create a new thread. When the newly created
thread starts, it will call the function pointed to by func and pass it the
single argument arg.
To test I wrote the following code:
void pHello(int i)
{
cout << "Hello from thread " << i << endl;
}
... [In Main] ...
typedef void (*thread_startfunc_t) (void* i);
thread_startfunc_t pSalute = & pHello; //Does not compile
thread_libinit(pSalute,1);
I receive the error:
In function `int main(int, char**)`:
error: invalid conversion from `void (*) (int)' to `thread_startfunc_t{aka void(*) (void*)}' [-fpermissive]
I thought a void pointer variable can point to any variable. So why can't it point to the int of the function pHello? How do I assign a function to the function pointer?
Upvotes: 1
Views: 1211
Reputation: 27518
I thought a void pointer variable can point to any variable. So why can't it point to the int of the function pHello?
Because the statement is not correct. In C++, you must use casts for this. This is one of the big differences between C++ and C. See also Difference between void pointers in C and C++
You can test this. Compile your code as C, remove C++ features like <iostream>
, and it should work as intended.
How do I assign a function to the function pointer?
Change the signature of pHello
to:
void pHello(void*)
Inside the function, you must use casts to obtain the value of the pointee.
Also, when you call thread_libinit
, the second argument must be the address of an int
object which lives until the function returns.
Of course, none of this is very nice or modern C++. Your professor's API should instead make use of std::function
.
Upvotes: 1
Reputation: 15468
A function pointer with a specific signature (given as return type plus variable types) can only point to functions having the same signature.
In your case, where it seems you can't change the function pointer type, you can change your function pHello
according to
void pHello(void* i)
{
std::cout << "Hello from thread " << *static_cast<int*>(i) << std::endl;
}
typedef void (*thread_startfunc_t) (void*);
int main()
{
thread_startfunc_t f = pHello;
//or point to a non-capturing lambda:
thread_startfunc_t f2 = [](void *) { std::cout<<"hi"<<std::endl; };
}
This is however not really nice C++ code.
Upvotes: 2