【问题标题】:"Candidate function not viable;" Issues with porting a C library to C++“候选函数不可行;”将 C 库移植到 C++ 的问题
【发布时间】:2013-06-10 12:24:54
【问题描述】:

我正在尝试在 c++ 实现中使用 c 库,但我经常遇到与“候选函数不可行”有关的错误,并且似乎认为库中的函数无法使用提供的参数在我的代码中。问题是,我的代码实际上是一个旧的实现(在 c 中),在 c 中编译时工作得非常好。有没有办法让这个编译成为我的 c++ 环境的一部分?

这是我得到的错误:

testbed/des-lsr_routinglogic.cpp:20:27: error: no matching function for call to 'dessert_periodic_add'
periodic_refresh_nh = dessert_periodic_add(refresh_list, NULL, NULL, &refresh_neighbor_t);
                      ^~~~~~~~~~~~~~~~~~~~
/usr/local/include/dessert.h:880:21: note: candidate function not viable: no known conversion from 'dessert_per_result_t ()' to 'dessert_periodiccallback_t *' (aka 'dessert_per_result_t (*)(void *, struct
  timeval *, struct timeval *)') for 1st argument
dessert_periodic_t* dessert_periodic_add(dessert_periodiccallback_t* c, void* data, const struct timeval* scheduled, const struct timeval* interval);
                ^

从这行代码代码:

periodic_refresh_nh = dessert_periodic_add(refresh_list, NULL, NULL, &refresh_neighbor_t);

使用这个库的摘录:

dessert_periodic_t* dessert_periodic_add(dessert_periodiccallback_t* c, void* data,     const struct timeval* scheduled, const struct timeval* interval);
dessert_periodic_t* dessert_periodic_add_delayed(dessert_periodiccallback_t* c, void* data, int delay);
int dessert_periodic_del(dessert_periodic_t* p);
void dessert_register_ptr_name(void* ptr, const char* name);
const char* dessert_ptr2name(void* ptr);

我认为编译器的输出对于任何有结合 c/c++ 经验的人来说应该是不言而喻的,但对我来说它看起来像胡言乱语 D:

编辑

谢谢,有人指出我遗漏了一些重要的定义; refresh_list的定义:

 dessert_per_result_t refresh_list(void *data, struct timeval *scheduled, struct timeval *interval) {
pthread_rwlock_wrlock(&pp_rwlock);
node_neighbors_t *neighbor = dir_neighbors_head;
while (neighbor) {
    if (neighbor->entry_age-- == 0) {
        node_neighbors_t* el_to_delete = neighbor;
        HASH_DEL(dir_neighbors_head, el_to_delete);
        free(el_to_delete);
    } else {
        neighbor->weight = 1;
    }
    neighbor = neighbor->hh.next;
}
pthread_rwlock_unlock(&pp_rwlock);
return 0; }

甜点_per_result_t的定义:

 typedef enum _dessert_periodic_results { DESSERT_PER_KEEP = 0, DESSERT_PER_UNREGISTER = 1 } dessert_per_result_t;

dessert_periodiccallback_t 的定义很奇怪;我会尝试发布它。

【问题讨论】:

  • 虽然编译器输出相当容易理解,但我们完全不知道refresh_list 是什么,因为您选择不告诉我们。
  • 请同时发布dessert_periodiccallback_tdessert_per_result_trefresh_list的声明。
  • 您正在传递一个结构并且库需要一个指针。啊,我们都,C,嗯?
  • typedef enum _dessert_periodic_results { DESSERT_PER_KEEP = 0, DESSERT_PER_UNREGISTER = 1 } dessert_per_result_t;
  • @KerrekSB: refresh_list 的类型为 dessert_per_result_t ()

标签: c++ c porting


【解决方案1】:

C++ 对函数声明比 C 更严格。在这种情况下,函数 refresh_list 被声明为 dessert_per_result_t refresh_list(),但 dessert_periodic_add 的第一个参数必须是指向具有显式指定参数类型的函数的指针。

解决此问题的最佳方法是添加一个完整的 refresh_list 声明,与 dessert_periodic_add 的预期相匹配,代替它的缩写声明。

【讨论】:

  • 感谢 David Foerster 的更正。我在一个小型设备上来回滚动以复制文本并撰写答案。
  • 现在我只需要问库的创建者到底应该在一个函数中作为参数传递什么我不知道什么时候我想在没有全局变量的情况下调用......哦,c ...
  • @GreyNewell:全局变量不是问题。参数类型是。显示了参数类型:dessert_periodic_add 需要一个指向带有两个参数的函数的指针,第一个是指向 void 的指针,另外两个是指向 struct timeval * 的指针,并返回 dessert_per_result_t。所以refresh_list 应该声明为dessert_per_result_t refresh_list(void *, struct timeval *, struct timeval *)
【解决方案2】:

编译器消息显示编译器认为refresh_list 是一个不带参数并返回dessert_per_result_t 的函数。

您发布的定义不同意。

这表明refresh_list的单独声明与定义不一致。

【讨论】:

  • 声明在C++中可能不一致,而在C中则不然。
  • 很有可能,是的。在这种情况下,他可能不得不修改库头文件。
  • 如果可能,我想避免修改标题,因为我的库在这个项目的多个地方使用。
  • 嗯,refresh_list 是你自己的函数,还是库的一部分?
【解决方案3】:

错误信息中refresh_list的声明是这样的:

dessert_per_result_t refresh_list();

这在 C++ 和 C 中意味着两种不同的东西。

在 C++ 中,这意味着 refresh_list 接受零参数。

在 C 中,这意味着 refresh_list 接受未指定数量的未指定类型的参数。

这就是为什么它在 C 中有效,但在 C++ 中,在需要指向 dessert_per_result_t(void *, struct timeval *, struct timeval *) 的指针的地方不允许使用指向 refresh_list 的指针。

另见:

【讨论】:

  • 编辑:删除了我太聪明的解决方案,因为你不能重载extern "C"函数:(
猜你喜欢
  • 2021-12-31
  • 1970-01-01
  • 2011-01-02
  • 2010-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-13
  • 1970-01-01
相关资源
最近更新 更多