4

次の質問の重複:C関数の競合


こんにちは、私の現在のプロジェクトでは、ある種のインターフェイスライブラリを使用する必要があります。関数名はこのインターフェースによって与えられます。この関数が行うことは開発者の選択です。私が知る限り、プロジェクトはこの関数を使用する必要があり、コンパイルに関しては、libとそれを使用して機能を選択します。私がやろうとしているのは、既存のlibと私のlibを同時に使用して、もう一方をラップし、それをmein関数で呼び出すことです。

otherlib:

int function1 (int a) {
// do something
}

mylib:

int function1 (int a) {
//my code here
    otherlib::function1(a);
}

問題は、他のlibにアクセスできず、他のlibに名前空間がないことです。私はすでに試しました

namespace old {
    #include "otherlib.h"
}

次に、私の関数でold::function1によって古い関数を呼び出します。これは、ヘッダーファイルのみである限り機能します。libは、そのシンボルをグローバル空間にエクスポートします。また、

namespace new {
    function1 (int a) {
        ::function1(a);
    }
}

動作しませんでした。最後になりましたが、ここで提案されているifdefsとdefinesを試しました

しかし、私は成功しませんでした。

これを解決する方法はありますか?前もって感謝します。

編集:私は古いライブラリにも、両方のライブラリが使用されるプロジェクトにもアクセスできません。

EDIT2:少なくとも古いライブラリは静的なものです

4

4 に答える 4

6

C の名前空間は、次のようなライブラリ名のプレフィックスを使用して解決されます。

libfoo -- > foo_function1
libbar --> bar_function1

これらのプレフィックスは実際の名前空間です。libbar と書くと

int bar_function1(int a) {
     function1(a);
}

これが問題を解決する方法です。

C には名前空間があります --- 接頭辞を呼び出しただけです ;)

別のオプションは、次のようなライブラリの動的ロードでさまざまな汚いトリックを行うことです。

h1=dlopen("libfoo.so")
foo_function1=dlsym(h1,"function1")

h2=dlopen("libbar.so")
bar_function1=dlsym(h2,"function1")
于 2009-03-25T11:42:55.817 に答える
4

他のlibがCであり、コードがC++であるかのように見えます。マングリングの問題が発生する可能性があります(C ++コンパイラはシンボルをマングルします-シンボル名に余分なものを追加すると、オーバーロードなどが区別されます)。

ライブラリが純粋なCの場合は、次のことを試すことができます。

extern "C" { // disable mangling of symbol names in the block
#include "otherlib.h"
}

namespace new_lib { // new is a reserved word
   int function1( int a ) {
      ::function1(a);
   }
}

私はそれを試していません。また、表示されるエラーメッセージを提供することを検討してください。

別のオプションは、(ライブラリが動的である場合)動的にライブラリをロードして関数を呼び出すことです。Linux(Windowsについてはわかりません)では、dlopenを使用してライブラリを開き、dlsymを使用してシンボルを取得して呼び出すことができます。

// off the top of my head, not tried:
int function1( int a )
{
   int (*f)(int); // define the function pointer
   void * handle = dlopen( "library.so" );
   f = dlsym( handle, "function1" );
   f( a ); // calls function1(a) in the dynamic library
}

この場合、ライブラリに対してリンクしていないため、シンボルの競合は発生しませんが、動的ライブラリに対してのみ有効であり、通常の使用では非常に面倒です。

アップデート

ユーザーが「otherlib」を直接使用せず(ヘッダーは含まれません)、C ++のみになる場合は、最初のアプローチが可能です(読むのが恐ろしい場合でも)。

// newlib.h
namespace hideout {
   int f( int a );
}
using namespace hideout; // usually I would not put this on the header

// newlib.cpp
extern "C" { // if otherlib is C, else remove this line
#include "otherlib.h"
}
namespace hideout {
   int f( int a ) { return ::f( a*2 ); }
}

// main.cpp
#include "newlib.h"
int main()
{
   std::cout << f( 5 ) << std::endl;
}

それはどのように機能しますか?ユーザーコードには、 otherlib.hが含まれていないため、function1の宣言(例ではf())のみが表示されます。コンパイルユニット内には2つの宣言がありますが、名前空間を使用することで区別されます。ヘッダーのusingステートメントは、cppで完全に修飾されているため、気になりません。ユーザーmain.cppにはヘッダーのみが含まれるため、コンパイラーはhideout :: fのみを認識し、usingステートメントによりどこにでも表示されます。C ++シンボルが実際の名前空間を識別するためにマングルされているため、リンカは問題ありません。

// g++ 4.0 in macosx:
00002dbe T __ZN7hideout9function1Ei // namespace hideout, function1 takes int, returns int
00002db0 T _function1

ユーザーコードにヘッダーとotherlib.hの両方が含まれる場合は、呼び出す関数を修飾する必要があります。

于 2009-03-25T11:50:14.673 に答える
1

本当に必死なら、名前空間やプレフィックスを使用するか、dlsym トリックを可能にするラッパー ライブラリを作成できます。このラッパー ライブラリは、動的にリンクする必要があります (シンボルの競合を避けるため)。動的ライブラリには、古い静的ライブラリを安全に埋め込むことができます。動的ラッパー ライブラリを作成するときに、静的ライブラリからシンボルをエクスポートしないようにしてください。

于 2009-03-25T18:27:46.997 に答える
1

これはリンク時に解決できないため、動的ライブラリを介して実行時に解決する必要があります。これらの関数のシンボルは、ライブラリが生成されると基本的に焼き付けられます。2 つのライブラリが同じシンボルをエクスポートする場合、両方を静的にリンクすることはできません。

于 2009-03-25T18:28:12.300 に答える