C program: pass function as parameter to another function to create thread - c

I would need some help. I been doing it for hours and is not able to get it to work. Generally, I have a function which access a kernel Driver and I would like to pass that function as a parameter to another function that include some pthread code. I researched and found out that I may need a function pointer.
Here is the function which I want to pass as a parameter.
static void kernelTest(char Send[BUFFER_LENGTH])
{
int fd = open("/dev/kernelTest", O_RDWR);
}
Here is the function which I want to pass in:
static void createKThread(void (*f)(char *))
{
pthread_t t1;
int ret;
ret = pthread_create(&t1, NULL, (*f)(char), NULL);
pthread_join(t1, NULL);
}
I attempted the function pointer but it is giving me error.
error: expected expression before ‘char’
I greatly appreciate any help rendered. Thank You!

(*f)(char) is invalid syntax. It looks like you're attempting to call the function f and passing char as a parameter, which you can't do.
Since you're not actually calling f, just pass it to pthread_create directly:
ret = pthread_create(&t1, NULL, f, NULL);
There's still a problem with this, however. The third parameter to pthread_create is expected to be of type void *(*)(void *), i.e. a pointer to a function that has a void * parameter and returns a void *. Your function has type void (*)(char *), so the parameters are incompatible.
You need to either change the signature of kernelTest to match what pthread_create expects:
static void *kernelTest(void *param)
{
char *send = param;
int fd = open("/dev/kernelTest", O_RDWR);
return NULL;
}
Or you need to create a wrapper function which matches pthread_create:
static void *kernelTest_wrapper(void *param)
{
char *send = param;
kernelTest(send);
return NULL;
}

Related

expected ')' before '(' token when using NULL macro in C

This is my code for a program that creates an environment to run a Java .jar file. I am using the _execl function and am programming on Windows:
#include <stdlib.h>
#include <stdio.h>
#include <process.h>
int setenv(const char *name, const char *value, int overwrite);
int main()
{
setenv("JAVA_HOME2", "path\\to\\java.exe", 1);
char *var, *param, *path;
var = getenv("JAVA_HOME2");
param = ("-jar");
path = ("path\\to\\foo.jar");
intptr_t _execl(var, param, path, NULL);
}
int setenv(const char *name, const char *value, int overwrite)
{
int errcode = 0;
if(!overwrite) {
size_t envsize = 0;
errcode = getenv_s(&envsize, NULL, 0, name);
if(errcode || envsize) return errcode;
}
return _putenv_s(name, value);
}
However, VS Code returns the error: expected ')' before '(' token on line 16, which is intptr_t _execl(var, param, path, NULL);.
Does anyone have any solutions?
You're getting an error here:
intptr_t _execl(var, param, path, NULL);
Because this is not a function call but a declaration of a function.
By putting a type name before the function, you're declaring that _execl is a function whose return value is of that type. The parameters given to the function are then taken as the names of those parameters, and since NULL is not a valid identifier for a parameter you get an error.
If you look at the several other places you call a function such as setenv and getenv you're not putting a type name first. So remove it:
_execl(var, param, path, NULL);
And now you have a function call.
This still won't call the function properly, however. The first argument is the path to the executable, and the remaining arguments are command line arguments to the program, and the first command line argument is the name of the program being run. So you actually want to call it like this:
_execl(var, var, param, path, NULL);
Or this:
_execl(var, "java", param, path, NULL);
Also, there's no need for parenthesis around a string constant when you assign it to something. So this:
param = ("-jar");
path = ("path\\to\\foo.jar");
Can be replaced with:
param = "-jar";
path = "path\\to\\foo.jar";
Or you can get rid of these temporaries entirely and pass the strings directly to _execl:
_execl(var, "java", "-jar", "path\\to\\foo.jar", NULL);

Can't get around to how to pass a function as a parameter

I'm trying to pass this function: void* checkMatrix(); as an argument to this function: void createThreads(void*(*f));.
I've read a post here so my decleration above is a result of this.
I'm calling the function like this: createThreads(checkMatrix); but it gives me a warning that type is incompatible [void** and void*()]. I can get around with a fast cast but it won't fix the problem.
Finally I write the function like this (simple initialization):
void createThreads(void* (*f)) {
pthread_t* a;
int i;
a = (pthread_t*) malloc(*arr.l * sizeof(pthread_t));
if (a == NULL) {
fprintf(stderr, "ERROR!\n");
exit(1);
}
for (i = 0; i < *arr.l; i++) {
if (pthread_create((a + i), NULL, (void*) &f, NULL)) {
fprintf(stderr, "ERROR IN THREAD CREATION!\n");
exit(2);
}
}
for (i = 0; i < *arr.l; i++)
pthread_join(*(a + i), NULL);
}
In conclusion, the problem is that it stops, with memory problem, but the cause is the creation of the threads and espacially in the 3rd argument that I specify the function that the thread will work on. I think I'm doing something wrong with the calling. I can't find the answer and can't get around it.
Thanks for your time!
void* (*f) is just void **f with a set of redundant parentheses. You probably wanted to use this for the parameter type:
void* (*f)()
However, that is not what pthread_create expects. The thread's main function is supposed to return void* and take a void* parameter. So what you really want is probably this:
void createThreads(void* (*f)(void*)) {
/* ... as before ... */
if (pthread_create((a + i), NULL, f, NULL)) {
/* ... as before ... */
}
To begin with void* checkMatrix(); is obsolete style and shouldn't be used. Second, pthread callback functions take void* as parameter. So use void* checkMatrix(void*); instead.
To pass it to a function, simply do
void createThreads (void* (*f)(void*))
Recommended practice when using function pointers is otherwise to use typedefs, to increase readability. For example you could cook up something like
typedef void* pthread_callback (void*);
void createThreads (pthread_callback* f)
Try changing the function signature to void createThreads(void* (*f)(void *))
and change the pthread_create function call topthread_create((a + i), NULL, f, NULL)

Passing function pointer to arg of pthread_create function

I have a function void startScanner(...) taking two function pointer as arguments: userType *vConfig(void) and void * vCallback(void). In this function i would like to create a thread and call vCallback() function in the function thread created. So i decided to pass vCallback as args to pthreadcreate.
The code of startScanner function :
void startScanner(tUsrStatus (*vConfig)(), void* (vCallback)()){
if(pthread_create(&scannerThread, NULL, scannerThreadFunc, vCallback))
{
printf("Thread creation fails!\n");
}
}
The scannerTread function:
static void *scannerThreadFunc(void *arg()){
void *funcptr(void) = arg;
while(1)
{
funcptr();
}
pthread_exit(NULL);
}
I get the following error:
error: function ‘funcptr’ is initialized like a variable
error: nested function ‘funcptr’ declared but never defined
How can i fix this?
Syntax errors aside (*) , it's impossible in standard C to pass a function pointer in a void *. There's a fundamental difference between pointers to functions and pointers to data, they can't be converted into each other. This is because there might be platforms where function and data pointers would differ even in size, or refer to different address spaces, or whatever.
But of course, there's a simple way to achieve what you want: Put your function pointer inside a struct and pass a pointer to that.
typedef (*callback)(void);
typedef struct threadargs
{
callback cb;
} threadargs;
void mycallback(void)
{
// ...
}
void *threadfunc(void *arg)
{
threadargs *ta = arg;
// call your callback:
ta->cb();
return ta; // or: return 0, or some pthread_exit(), ...
}
int main(void)
{
pthread_t thread;
threadargs ta = { mycallback };
pthread_create(&thread, 0, threadfunc, &ta);
// make sure "ta" lives for as long as the thread executes,
// here just wait until it exits:
pthread_join(&thread, 0);
}
add error checking etc.
(*) as for the concrete error you're getting, a function pointer needs parantheses around the identifier, so instead of
void *funcptr(void) = arg;
you'd have to write
void (*funcptr)(void) = arg;
To facilitate the usage of function pointers, it's common to typedef them, as seen in my example above. Anyways, as explained above, this wouldn't solve your problem here.

C - pthread arguments

It is the first time that I am working with threads in C and I am getting problems passing function arguments. For some reasons I need to create this thread.
I have a function that sends a messages to a server. The header of my function is:
void* sender (char* payload, void (*Callback)(char*))
Then on my main (simplified), I create the following thread:
main ()
{
pthread_t sender_id;
int err_s;
err_s = pthread_create (&sender_id, NULL, &sender, NULL);
}
The problem is that my function sender has many arguments so I am getting this error:
note: expected 'void * (*)(void *)' but argument is of type 'void * (*)(char *, void (*)(char *))'
I would be gratefull if sombody could help me.
You can just create a structure lets say:
struct thread_prm
{
char *payload;
void (*Callback)(char*) cb;
}
And you just allocate a structure that looks like this and pass it to pthread_create as the last argument. Like this:
struct thread_prm *arg;
arg = malloc(sizeof(struct thread_prm));
(assign arg members to something)
pthread_create(&sender_id, NULL, &sender, arg);
And you modify sender:
void* sender (void *arg)
{
struct thread_prm *_arg = arg;
char* payload;
void (*Callback)(char*) cb;
payload = _arg->payload;
cb = _arg->cb;
...
}

makecontext function pointer [error: invalid use of void expression]

I have the following code (its for an threads library to a class):
int tcb_context_create(TCB *thread, void (*start)(void*), void *arg) {
if (!makecontext( &(thread->context), (void (*) (void)) start, 1, arg)) {
errno = EAGAIN;
return -1;
}
return 0;
}
But i the compiler keep giving 'error: invalid use of void expression' i have searched everywhere and cant find the corrent way to use the makecontext function.
corrected:
int tcb_context_create(TCB *thread, void (*start)(void*), void *arg) {
makecontext( &(thread->context), (void (*) (void)) start, 1, arg);
return 0;
}
The return type of makecontext is void. Using ! on a void is not correct.
In addition, you don't have a return statement outside the if block. Since the function's return type is int, you need to add a proper return statement. Otherwise, you will run into undefined behavior.

Resources