2016-10-25 8 views
3

Xcode 7.2.1でビルドされ、GNU ++ 98の方言でコンパイルされ、libstdC++とリンクされたC++アプリケーションがあります。 C++ 11でコンパイルされ、libC++とリンクされたdylibを呼び出す必要があります。 dylibのクラスメンバのデフォルトの属性の可視性使用GNU ++ 98/libstdC++に対してコンパイルされたアプリは、C++ 11/libC++に対して構築されたdylibにリンクできますか?

extern __attribute__((visibility("default"))) void foo(std::string const&, int); 

...そこに示しては(少なくとも文字列の)ABIの互換性はありません - STDのPARAMを持つ任意のdylib機能: :文字列をアプリにリンクすることはできません。

dylib側で構築されたchar * paramsをstd :: stringに渡すだけのオーバーロードされたC++メンバー関数を作成する適切なソリューションか、dylib用の純粋なC APIの作成を必要とするその他の問題があります?

注:今ABIの互換性の問題にThis excellent explanationを読んだ、確か少し希望がありますようだがのstd ::文字列のparamsのために構築された文字ベースのAPIへ...

+0

文字列ビュー型クラスを作成しますか?あるいは配列ビューさえ。 std stringと標準レイアウトからの暗黙的な変換 – Yakk

+0

あなたはdylibの一部ではないクラスを意味しますか?または、それがdylibのヘッダーの一部だった場合は、ヘッダー専用のクラスになりますか? – SMGreenfield

答えて

1

は、標準的なレイアウトを使用して、あなたのAPIを書きますクラス。

標準的なレイアウトクラスは非常に派手なものです。

は、ここに私の頭の上からコンパイルされていないarray_viewです:

template<class Container> 
using data_ptr_type = decltype(std::declval<Container>().data()); 

template<bool b> 
using bool_kt = std::integral_constant<bool, b>; 

template<class T> 
struct array_view { 
    T* b = nullptr; 
    T* e = nullptr; 
    T* begin() const { return b; } 
    T* end() const { return b; } 
    template<class U> 
    using ptr_is_compatible = bool_kt< 
    std::is_same< U, T* >{} || std::is_same< U, std::remove_const_t<T>* >{} || 
    std::is_same< U, std::remove_volatile_t<T>* >{} || std::is_same< U, std::remove_cv_t<T>* >{} 
    >; 

    // convert from .data() and .size() containers: 
    template<class In, 
    std::enable_if_t< 
     ptr_is_compatible< data_ptr_type< In& > >{}, int 
    > = 0 
    > 
    array_view(In&& in):array_view(in.data(), in.size()) {} 

    // special ones: 
    array_view()=default; 
    array_view(array_view const&)=default; 
    array_view& operator=(array_view const&)=default; 

    // manual ones: 
    array_view(T* ptr, std::size_t N):array_view(ptr, ptr+N) {} 
    array_view(T* s, T* f):b(s), e(f) {} 

    // from C-style array: 
    template<class U, std::size_t N, 
    std::enable_if_t< 
     ptr_is_compatible< U* >{} 
    ,int> = 0 
    > 
    array_view(U(&arr)[N]):array_view(arr, N) {} 

    template<class Container> 
    Container copy_to() const { 
    return {begin(), end()}; 
    } 
}; 

空想が、それは標準レイアウトです。だから、最も狂ったABIの変化だけがそれを打破するだろう。

extern __attribute__((visibility("default"))) void foo(array_view<const char>, int); 

を、呼び出し側はfoo("hello", 7)またはfoo(std::string("hello"), 42)またはfoo(std::vector<char>{'a', 'b', 'c'}, 18)または何でそれを呼び出すことができます。

今すぐあなたのヘッダファイルを読み込みます。あなたは気にしない。

バッファの先頭へのポインタは呼び出し元側で行われるため、渡されたもののレイアウトは分かりません。

必要に応じて、内部でarg.to<std::string>()を使用してコンテナにマーシャリングすることができます。

関連する問題