【问题标题】:Passing function pointer to arg of pthread_create function将函数指针传递给 pthread_create 函数的 arg
【发布时间】:2018-04-23 08:50:59
【问题描述】:

我有一个函数void startScanner(...) 以两个函数指针作为参数:userType *vConfig(void)void * vCallback(void)。在这个函数中,我想创建一个线程并在创建的函数线程中调用vCallback() 函数。所以我决定将 vCallback 作为参数传递给 pthreadcreate。 startScanner 函数代码:

void startScanner(tUsrStatus (*vConfig)(), void* (vCallback)()){

    if(pthread_create(&scannerThread, NULL, scannerThreadFunc, vCallback))
    {
        printf("Thread creation fails!\n");
    }
}

scannerTread 函数:

static void *scannerThreadFunc(void *arg()){

    void *funcptr(void) = arg;

    while(1)
    {
        funcptr();
    }
    pthread_exit(NULL);
}

我收到以下错误:

error: function ‘funcptr’ is initialized like a variable
error: nested function ‘funcptr’ declared but never defined

我该如何解决这个问题?

【问题讨论】:

  • 你看到你在第一个 sn-p 中的第二个参数和你在第二个 sn-p 中的 funcptrdecl 之间有什么区别吗?嗯....(提示:请重新检查 arg 的语法)。我几乎可以肯定所有这些案例都应该是void *(*varname)(void)。也就是说,如果您传递的函数地址 (a) 返回 void*,并且 (b) 不接受任何参数。

标签: c linux pthreads function-pointers


【解决方案1】:

除了语法错误 (*) 之外,在标准 C 中不可能void * 中传递函数指针。指向函数的指针和指向数据的指针之间存在根本区别,它们不能相互转换。这是因为在某些平台上,函数和数据指针的大小可能会有所不同,或者引用不同的地址空间等等。

当然,有一个简单的方法可以实现你想要的:将你的函数指针放在 struct 中,然后传递一个指向它的指针。

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);
}

添加错误检查等


(*) 至于你得到的具体错误,函数指针需要在标识符周围加上括号,所以不是

void *funcptr(void) = arg;

你必须写

void (*funcptr)(void) = arg;

为了方便函数指针的使用,typedef 它们很常见,如我上面的示例所示。无论如何,如上所述,这不会解决您的问题。

【讨论】:

  • 不需要创建特殊的结构体,将指针传递给指针就足够了。
  • @n.m.也许我误读了这个问题,我的印象是最终目标是传递 两个 指针。无论如何,结构不会受到伤害并且是通用的解决方案。
  • 谢谢Felix,我是这样写的。不再存在编译问题,但是当它尝试执行回调函数“ta -> cb()”时出现 SIGSEGV sigmentation 错误。这是我的代码:pastebin.com/LDistHye
  • @julesconté 查看我的评论“确保“ta”在线程执行期间一直存在”。你没有在你的代码中。一种选择是将其声明为static,这取决于您的用例。
  • @FelixPalmen,它适用于静态声明。但是有没有最好的方法在函数线程中实现回调函数呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多