[英]Use pthread_create to invoke a C function of the type “int argc, char** argv -> int”
I need to use pthread_create to invoke a C function of type 我需要使用pthread_create来调用类型为C的函数
int main_original(int argc, char** argv)
I have tried something like this: 我已经尝试过这样的事情:
pthread_create(&t, NULL, main_original, NULL);
The compiler gives me a type error 编译器给我一个类型错误
invalid conversion from 'int (*)(int, char**)' to 'void* ( )(void )'
从'int(*)(int,char **)'到'void *( )(void )'的无效转换
So, what is the right way to invoke main_original so that its parameters are well passed? 那么,调用main_original以便正确传递其参数的正确方法是什么?
The function pthread_create
is only able to call functions with the following signature: 函数
pthread_create
仅能够调用具有以下签名的函数:
void *fn(void *)
Even if you did manage to cast a pointer to a function with a different signature and successfully pass it to pthread_create
, your program is likely to crash as pthread_create
will attempt to set up the stack / registers in a way that follows the platform's calling convention for a function with just one void *
argument, which will lead to your function being in an indeterminate state. 即使您确实设法将指针转换为具有不同签名的函数并将其成功传递给
pthread_create
,您的程序也可能会崩溃,因为pthread_create
会尝试按照平台的调用约定来建立堆栈/寄存器。一个仅带有一个void *
参数的函数,这将导致您的函数处于不确定状态。
The way to solve your problem would be to use a wrapper function specifically designed for being called by pthread_create
like so: 解决问题的方法是使用专门为
pthread_create
调用而设计的包装器函数,如下所示:
void *main_original_start_routine(void *arg)
{
main_original(argc, argv);
return NULL;
}
However, this may not be enough, unless argc
and argv
are global variables. 但是,除非
argc
和argv
是全局变量,否则这可能还不够。 You may find you also need to somehow pass these values through to this function from the scope in which you call pthread_create
. 您可能会发现还需要以某种方式将这些值从调用
pthread_create
的范围传递到此函数。 This can be done via the void *arg
argument to pthread_create
, by creating a struct holding the state you need, and passing it around via a casted void pointer: 可以通过创建
pthread_create
的void *arg
参数来实现,方法是创建一个保存所需状态的结构,然后通过强制转换的void指针将其传递给周围:
struct main_original_context {
int argc;
char **argv;
};
void *main_original_start_routine(void *arg)
{
/* Convert the void pointer back to the struct pointer it
* really is. */
struct main_original_context *ctx = arg;
main_original(ctx->argc, ctx->argv);
return NULL;
}
int main(int argc, char **argv)
{
pthread_t t;
struct main_original_context ctx = {
argc,
argv
};
/* Pass a pointer to our context struct to the thread routine. */
pthread_create(&t, NULL, &main_original_start_routine, &ctx);
pthread_join(&t, NULL);
return 0;
}
Keep in mind however, that ctx
only has a lifetime of the duration of the main
function in this case. 但是请记住,在这种情况下
ctx
仅具有main
函数持续时间的生存期。 If the function we create the pthread in does not join with pthread_join
before returning (and invalidating the struct used to provide context to the thread), then this would be unsafe. 如果我们在其中创建pthread的函数在返回之前未与
pthread_join
连接(并使用于向线程提供上下文的结构无效),那么这将是不安全的。 Therefore we would have to use dynamic allocation, and make the thread assume responsibility for freeing any dynamically allocated memory: 因此,我们将不得不使用动态分配,并使线程承担释放任何动态分配的内存的责任:
struct main_original_context {
int foo;
int bar;
};
void *foobar_start_routine(void *arg)
{
struct main_original_context *ctx = arg;
foobar(ctx->foo, ctx->bar);
/* Free memory we have been given responsibility for. */
free(ctx);
return NULL;
}
void asdf(int foo, int bar)
{
pthread_t t;
struct main_original_context *ctx;
/* Allocate memory. */
ctx = malloc(sizeof *ctx);
ctx->foo = foo;
ctx->bar = bar;
/* Assume `main_original_start_routine` is now responsible for freeing
* `ctx`. */
pthread_create(&t, NULL, &foobar_start_routine, ctx);
/* Now we can safely leave this scope without `ctx` being lost. In
* the real world, `t` should still be joined somewhere, or
* explicitly created as a "detached" thread. */
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.