代码之家  ›  专栏  ›  技术社区  ›  vlad_tepesch

c++调用c函数(如果存在)

  •  1
  • vlad_tepesch  · 技术社区  · 6 年前

    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 必须看起来像这样,以便在那里的情况下可以编译/运行一些cpp代码 someFun 是否存在?如果不存在?

    这有可能吗?

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

    0 回复  |  直到 6 年前
        1
  •  1
  •   Jarod42    6 年前

    // "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
    }
    
        2
  •  0
  •   Michael Kenzel    6 年前

    是否有一个与外部联系的符号的定义的问题,本质上是一个问题,只能在连接时回答。在编译单个C++源文件时,编译器没有办法知道是否有其他外部函数的定义。在最好的情况下,SFINAE可以检查某个函数是否正确 . SFINAE不可能确定链接器以后是否会找到该函数的定义。

    如果C库带有头,可以包含在C++中,并且只有在C库的特定版本定义它们时,才声明所涉及的函数,可以使用像JAROD42的回答中所描述的AQuooCH。

    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