c++调用c函数,如果它确实存在

Posted

技术标签:

【中文标题】c++调用c函数,如果它确实存在【英文标题】:c++ call c function if it does exist 【发布时间】:2019-12-04 12:32:43 【问题描述】:

我有一些自动生成的 C++ 代码来包装一些 C 代码。

C 代码具有可预测的结构,但它具有/没有特定功能。

由于 C++ 代码是从没有此信息的描述中派生的。我想使用模板处理器来决定是否可以调用这个函数。

小例子:

struct SomeStruct
  int indicatorMember;
;
extern "C" void someFun(struct SomeStruct* somePointer)




void someCPPcode()
  SomeStruct s;
  // do something

  someMechanismToCall_someFunIfExists(&s);

  // do something other

someMechanismToCall_someFunIfExists 的外观如何,以便在someFun 确实存在且不存在的情况下可以编译/运行一些CPPcode?​​p>

这可能吗?

如果某个成员是结构的一部分,也可以确定该函数是否存在。 所以,如果indicatorMember确实存在,那么该函数也存在。

【问题讨论】:

如果你的 C++ 代码是自动生成的,你不能在生成器本身中包含这个逻辑吗? IE。仅当它可以在 C 源代码中找到函数时才生成调用。 您可能会在此链接中找到一些提示:how-to-check-if-the-function-exists 这能回答你的问题吗? Is it possible to write a template to check for a function's existence? 如果您有一些结构指标方法/字段,那么链接问题中有 SFINAE 方法。 @DanM。生成器不知道 c 源。它使用不包含此信息的定义语言 【参考方案1】:

您可以使用优先级较低的重载来解决您的问题:

// "C-Header"
struct SomeStruct

  int indicatorMember;
;

// Present or not
extern "C" void someFun(struct SomeStruct* somePointer)



// Fallback
void someFun(...)  /*Empty*/ 

void someCPPcode()

  SomeStruct s;
  // do something

  someFun(&s);

  // do something other

如果某个成员是结构的一部分,也可以确定该函数是否存在。所以,如果indicatorMember确实存在,那么该函数也存在。

有几种方法可以检测成员的存在,例如使用std::experimental::is_detected

但是在模板之外,你仍然有问题:

decltype(auto) someFunIfExists([[maybe_unused]] SomeStruct* p)

    if constexpr (has_someFunc<SomeStruct>::value) 
        return someFun(p); // Not discarded as you might expect -> Error
    

因为if constexpr (false) static_assert(false); 无效)。

所以你必须将函数包装在模板中:

template <typename T>
decltype(auto) someFunIfExists([[maybe_unused]] T* p)

    if constexpr (has_someFunc<T>::value) 
        return someFun(p);
    


void someCPPcode()
  SomeStruct s;
  // do something

  someFunIfExists(&s);

  // do something other

【讨论】:

问题在于,它仍然是声明了哪些函数而不是定义了哪些函数的问题。如果 C 库没有定义函数,您将不得不以某种方式使 C 库函数的所有声明消失…… 不确定“输入”(我们是否有 c-header,OP 是否生成 C++ 代码,...)【参考方案2】:

是否有外部链接的某个符号的定义的问题本质上是一个只能在链接期间回答的问题。在编译单个 C++ 源文件的过程中,编译器无法知道是否会在其他地方定义某些外部函数。在最好的情况下,SFINAE 可以检查某个函数是否已声明。 SFINAE 无法确定链接器稍后是否会找到该函数的定义。

如果 C 库带有可以包含在 C++ 中的标头,并且仅在 C 库的特定版本定义了它们时才声明有问题的函数,则可以使用 Jarod42 的答案中描述的方法。

否则,我能想到的最好的办法就是将函数的默认实现定义为始终定义的weak symbols,例如:

struct SomeStruct

    int indicatorMember;
;

extern "C" void someFun(SomeStruct* somePointer) __attribute__((weak))

    // do whatever this should do in case the C library does not define this function

弱符号不是标准 C++ 的一部分,因此执行此操作的确切机制取决于您的编译器和平台。以上将是 GCC 的一个示例。 MSVC 有一个未记录的链接器标志/alternatename,它允许为符号提供默认定义,请参阅this answer。

在链接过程中,如果链接器从您的 C 库中找到相同符号的非弱定义,它将选择那个,否则它将选择您的默认实现……

【讨论】:

以上是关于c++调用c函数,如果它确实存在的主要内容,如果未能解决你的问题,请参考以下文章

C++在构造函数中调用最终的虚函数

函数申明对函数模板实例化的屏蔽

C语言和C++的区别

在 C++ 中抛出后会调用析构函数吗?

主函数可以在C ++中调用自身吗?

C++,QT。 QShortcut 的函数调用不存在