函数指针typedef在c中

时间:2016-10-27 15:19:51

标签: c pthreads typedef

我有一些嵌入式操作系统功能,我需要在linux机器上进行模拟。我被指示采取的方法是重载嵌入式操作系统功能并将它们包装在POSIX线程中,以便linux机器可以在单元测试期间处理嵌入式操作系统功能等等。

用于创建新线程的嵌入式OS功能是: OSCreateTask(OStypeTFP functionPointer, OSTypeTcbP taskId, OStypePrio priority)

我需要将OStypeTFP类型转换为pthread_create期望的void函数指针:(void * (*)(void *)是编译器告诉我的预期)

我希望创建一个我可以使用它的typedef:

typedef void (*OStypeTFP)(void);

// Function to run task/thread in
void taskFunction(void) { while(1); }

// Overloaded Embedded OS function
void OSCreateTask(OStypeTFP tFP, OStypeTcbP tcbP, OStypePrio prio)
{
  pthread_attr_t threadAttrs;
  pthread_t thread;

  pthread_attr_init(&threadAttributes);
  pthread_create(&thread, &threadAttributes, &tFP, NULL);
}

// Creates a task that runs in taskFunction
OSCreateTask (taskFunction, id, prio);

但是当pthread_create期望functionPointer

时,编译器会抱怨void (**)(void)的类型为void * (*)(void *)

我是否需要以某种方式更改typedef,还是需要进行类型转换?既?

2 个答案:

答案 0 :(得分:5)

您需要适配器功能:

typedef void (*OStypeTFP)(void);

// Function to run task/thread in
void taskFunction(void) { while(1); }

void *trampoline(void *arg) 
{
    OStypeTFP task = (OStypeTFP)arg;
    task();
    return NULL;
}    

// Overloaded Embedded OS function
void OSCreateTask(OStypeTFP tFP, OStypeTcbP tcbP, OStypePrio prio)
{
  pthread_attr_t threadAttrs;
  pthread_t thread;

  pthread_attr_init(&threadAttrs);
  pthread_create(&thread, &threadAttrs, trampoline, tFP);
}

// Creates a task that runs in taskFunction
OSCreateTask (taskFunction, id, prio);

当然,只有当系统允许从void *转换为函数指针时,它才是安全的。但由于我们处于POSIX环境 - 它应该没问题。

答案 1 :(得分:3)

如果我理解正确,嵌入式操作系统上的线程过程的签名是void thread_proc(void)。另一方面,对于POSIX线程,它是void *thread_proc(void *)

您无法使用强制转换和typedef来解决这种差异:您需要安排适当的返回值。你需要一个垫片功能:

typedef void (*OStypeTFP)(void);
struct emu_OSCreateTask_thread_start_data
{
    OStypeTFP real_thread_proc;
    // possibly other stuff
};

void *emu_OSCreateTask_shim_thread_proc (void *xctx)
{
    struct emu_OSCreateTask_thread_start_data *ctx = xctx;

    ctx->real_thread_proc();
    return 0;
}

void OSCreateTask(OStypeTFP tFP, OStypeTcbP tcbP, OStypePrio prio)
{
    pthread_attr_t threadAttrs;
    pthread_t thread;
    struct emu_OSCreateTask_thread_start_data *ctx =
        malloc(sizeof(struct emu_OSCreateTask_thread_start_data));

    ctx->real_thread_proc = tFP;

    pthread_attr_init(&threadAttributes);
    pthread_create(&thread, &threadAttributes,
                   emu_OSCreateTask_shim_thread_proc, ctx);
}

注意:ctx在堆上分配并泄露,因为它需要在emu_OSCreateTask_shim_thread_proc返回之后存活,这可能比OSCreateTask返回时更晚。如果您不了解有关您尝试模拟的API的更多信息,我无法告诉您应该将它存放在何处,以便在适当时可以释放它,但可能会在某处 。也许在tcbP

注2:我使用上下文对象而不是仅填充" real_thread_proc"在pthread_create的上下文指针中(如在Sergio的答案中),因为我怀疑你最终需要在垫片中做更多的东西,并且需要更多来自外部环境的数据才能完成它。 (您在POSIX系统上,因此 可以安全地将函数指针填充到void *中。)