3

Cで書かれたサードパーティのライブラリAPIをDに翻訳しています。そのライブラリはlibname_foofunclibname_barfuncなどの名前の関数をたくさんエクスポートしています。これは、Cライブラリがグローバル名前空間の肥大化を防ぐために期待できます。D は C よりもモジュール化されているため、より D っぽいインターフェイスを提供し、関数のプレフィックスを取り除きたいので、関数は and のようlibname.c.foofuncになりlibname.c.barfuncます。

ライブラリは私の「改善」を認識していないため、何らかの方法で変換libname.c.foofunclibname_foofunc、正しい extern-linkage、宛先名マングリング、および呼び出し規約を同時に保持する必要があります。

__imp__D1c7foofuncFZi外部の未解決のシンボルが対応することをリンカに伝える方法があると仮定すると(私も知りません)、_libname_foofuncまたはlibname_foofunc@0(手で名前マングリングをしなければならないという事実にもかかわらず)、呼び出し規約が何であるかをDに伝える問題がまだあります。

で明示的に指定extern(C) int foofunc()した場合libname/c.di、呼び出し規約の問題はなくなりましたが、名前が に変換され_foofunc、これも予想とは異なります。

では、エクスポートされたものとは異なる名前で外部関数をインポートする方法はありますか?

関数を元の名前で「そのまま」インポートしてから、それらを接頭辞のない類似体にエイリアスすることについては考えましたが、これはかなり不器用なようです。

4

4 に答える 4

3

あなたが使用することができます

alias libname_foofunc foofunc;

これにより、表示されたままになりlibname_foofuncますが、使用できるようにfoofuncなり、コンパイラによって次のように変換されますlibname_foofunc

于 2012-04-05T14:16:18.527 に答える
2

OT の最後の段落を考慮すると、答えは NO です。あなたが説明したように、他のどの言語もそれを行うことはできませんし、そうすべきではありません。API 設計者が好きなように関数名を付けたい場合は、そのように公開します...

ここで、 を好む開発者のグループ A some_function()、次に を好むグループ B someFunction()、そして を好むグループ C を想像してみてくださいSomeFunction()

D を使用するか他のものを使用するかに関係なく、エイリアシングは必須です。そして、それはそのようであるべきです。API はシンプルかつ簡潔で、理解しやすいものにする必要があります。

于 2012-04-05T15:44:54.337 に答える
2

リンクに関する限り、C リンカについて話しているので、シンボルは実際には C のものです。リンクとエクスポートされたシンボルに関する D の状況は、基本的に C++ の場合と同じです。元の名前を使用して、D でそれらの宣言を作成する必要があります。これは、リンカーが期待するものだからです。Dは、それを変える何か違うことや魔法のことはしません。異なる名前を使用できるようにする方法は 2 つしかありません。

  1. D コード内の関数に別名を付けます。シンボルをリストするモジュールにエイリアスを配置するだけです(とにかくDで宣言する必要があるため)。その後、コードは元の名前またはエイリアスのいずれかを使用できます。私はそれについて不器用なことは何も見ていません。

  2. C または D でラッパー関数を作成し、D コードでそれらを使用します。

エイリアスは間違いなく私見の方が良いでしょう。オーバーヘッドが発生せず、複雑さが軽減されます。

ただし、D から C ライブラリを使用する場合の通常の処理は、C 関数名を使用することだけです。あなたは C 関数を呼び出しており、その事実を隠してはいけません。それらは D 関数ではなく、同じように動作しません (たとえ似ていても) - 特に、関数に渡すもののメモリを誰が所有するかなどに関しては。それらの名前を変更することの利点は議論の余地があります。通常、C 関数が直接使用されなくなったのは、API に (名前を変更するだけでなく) よりクリーンで D に似た API を提供するために D ラッパーが作成されたときです。Phobos でのこの良い例は、etc.c.curl と std.net.curl です。etc.c.curl は純粋に C API であり、何も名前を変更しようとしません。シンボルをフォボスの命名規則に一致させたり、より D に似せたりするためのエイリアスは作成されません。これ' 基本的に、curl のヘッダー ファイルの D バージョンにすぎません。一方、std.net.curl はその上に構築され、より D に似た API と抽象化を提供します。C 関数の名前を変更するだけではありません。

于 2012-04-05T17:00:53.693 に答える
1

関数をモジュールに入れたくない場合は、それらを構造体内に保持して、ある種の名前空間をシミュレートできます。たとえば、これを行うことができます:

struct libname
{
    struct C
    {
        static int libname_foofunc();
        alias libname_foofunc foofunc;
    }

    static C c;
}

void main()
{
    libname.c.foofunc();
}
于 2012-04-05T18:46:29.023 に答える