[如果存在,则c调用c函数

问题描述 投票:1回答:2

我有一些自动生成的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存在或不存在的情况下可以编译/运行一些CPP代码?

这甚至有可能吗?

如果某个成员是结构的一部分,也可以确定此功能是否存在。因此,如果indicatorMember存在,则该函数也存在。

c++ sfinae
2个回答
0
投票

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

// "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

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

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

0
投票

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

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

否则,我想到的最好的事情是将函数的默认实现定义为始终定义的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 } ,例如:

weak symbols

弱符号不是Standard C ++的一部分,因此执行此操作的确切机制取决于您的编译器和平台。以上是GCC的示例。 MSVC具有未记录的链接器标记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 } ,该标记允许为符号提供默认定义,请参见/alternatename

在链接期间,如果链接器发现来自您的C库的同一符号的非弱定义,它将选择该符号,否则将选择您的默认实现…

© www.soinside.com 2019 - 2024. All rights reserved.