ODR and C++ Versioning for Shared Library Wrapper

61 Views Asked by At

For simplicity, I will omit things like proper typedefs to opaque structs instead of void *, Windows calling conventions, fixed integer types, etc.

Suppose I have the following files:

CApi.h -- Shared library header with C linkage for portability and hiding proprietary code.

#define LIB_API  // library import/export details

extern "C" {

typedef int error;

error LIB_API lib_foo_create(void ** foo);
error LIB_API lib_foo_destroy(void * foo);
error LIB_API lib_foo_func(void * foo, int * out);

error LIB_API lib_bar_create(void ** bar);
error LIB_API lib_bar_destroy(void * bar);
error LIB_API lib_bar_func(void * bar, int * out); // Suppose this internally uses Foo::func from CxxApi.hpp with C++17

} // extern C

CxxApi.hpp -- Header only wrapper to simplify API usage.

#include "CApi.h"

namespace lib {

namespace detail {

template < typename Return = void, typename Func, typename... Args >
Return c_api(Func func)
{
    // Not sure how this affects ODR if client and provider code use different versions,
    // but neither see each other's code usage.

    #if __cplusplus >= 201703L // C++17
    // more efficient implmentation (e.g. fold expressions)
    #else
    // fallback implmentation (e.g. recursion)
    #endif
}

} // namespace lib::detail

class Foo
{
public:
    Foo() { detail::c_api(lib_foo_create, &handle_); }

    ~Foo() { detail::c_api(lib_foo_destroy, handle_); }

    int func() { return detail::c_api<int>(lib_foo_func, handle_); }

private:
    void * handle_;
};

struct Bar
{
public:
    Bar() { detail::c_api(lib_bar_create, &handle_); }

    ~Bar() { detail::c_api(lib_bar_destroy, handle_); }

    int func() { return detail::c_api<int>(lib_bar_func, handle_); }

private:
    void * handle_;
};

} // namespace lib

If I, the API provider, compile this using C++17, but the client using the API uses C++11, is ODR violated with lib::detail::c_api? I believe it is not because lib_bar_func's definition is in a different translation unit than client code, but I am not positive.

0

There are 0 best solutions below