首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Type cast void*(*)(void*) to void(*)(void)

Type cast void*(*)(void*) to void(*)(void)
EN

Stack Overflow用户
提问于 2013-01-26 04:46:35
回答 3查看 2.2K关注 0票数 4

作为任务的一部分,我正在尝试创建一个用户级线程库,比如pthread。

为了处理线程之间的上下文切换,我使用了“swapcontext”函数。在使用它之前,我必须使用'makecontext‘函数创建一个上下文。“(void)”需要返回类型为void且参数类型为‘makecontext的函数指针。

然而,线程函数必须是void* thread_func (void*)类型

有没有一种方法可以进行类型转换?或者,是否有其他方法可以在用户级别进行上下文切换?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-01-26 05:03:43

通过将函数的地址转换为不同的原型并通过结果指针调用该函数,使用不兼容的原型调用该函数是非法的:

代码语言:javascript
复制
void *my_callback(void *arg) { ... }

void (*broken)(void *) = (void (*)(void *)) my_callback;
broken(some_arg);   // incorrect, my_callback returns a `void *`

你能做的就是把你自己的回调传递给makecontext,这个回调会调用thread_func并忽略它的返回值。一个仅用于调用另一个函数的小函数有时被称为。

代码语言:javascript
复制
/* return type is compatible with the prototype of the callback received
   by makecontext; simply calls the real callback */
static void trampoline(int cb, int arg)
{
  void *(*real_cb)(void *) = (void *(*)(void *)) cb;
  void *real_arg = arg;
  real_cb(real_arg);
}

int my_pthread_create(void *(*cb)(void *), void *arg)
{
  ucontext_t *ucp;
  ...
  /* For brevity treating `void *` as the same size as `int` -
     DO NOT USE AS-IS.
     makecontext exposes an annoyingly inconvenient API that only
     accepts int arguments; correct code would deconstruct each
     pointer into two ints (on architectures where pointer is
     larger than int) and reconstruct them in the trampoline. */
  makecontext(ucp, trampoline, 2, (int) cb, (int) arg);
  ...
}

对于加分点,可以修改跳床以将回调函数返回的void *值存储在堆栈上,并让等效的pthread_join()检索该值。

票数 7
EN

Stack Overflow用户

发布于 2013-01-26 05:04:51

原则上,您总是可以将任何类型的指针转换为任何其他类型的指针,但是对于函数指针,我强烈建议不要使用。

您的thread_func将在堆栈上期望一个参数,如果在错误转换后调用该参数,则不会提供该参数。更糟糕的是,thread_func将在它不应该写入返回值的地方写入一个返回值,从而损坏堆栈。

一种解决方案是将调用包装在它自己的适当类型的函数中。

票数 4
EN

Stack Overflow用户

发布于 2013-01-26 05:03:51

你可以像变量一样对函数指针进行类型转换。语法更加笨拙,但这当然是可能的(这是否是一个好主意完全是另一回事)。

然而,在这种情况下,这可能不是您想要做的。从man page for swapcontext

在调用makecontext()之前,调用者必须为此上下文分配一个新堆栈,并将其地址分配给ucp->uc_ stack,

你的线程函数需要一个参数。通过您创建的堆栈将该参数传递给新的上下文。传递给makecontext()的函数可以是包装函数,它从堆栈中检索值并将其作为参数传递给线程函数。类型转换本身不能提供将参数中的数据向下传递到新上下文中的函数的方法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14530109

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档