スクリプト言語のネイティブ拡張-名前の衝突を回避し、他の人の名前空間を混乱させる


8

小さなスクリプト言語を開発し、最初のネイティブライブラリバインディングの作成を開始しました。これは、スクリプト言語のネイティブ拡張を書いているのは事実上初めてなので、概念的な問題に遭遇しました。

この言語から使用できるように、一般的なライブラリのグルーコードを書きたいと思います。私が書いたエンジンの設計により、これはstruct、仮想マシン、および関数ポインタ。

したがって、ネイティブバインディングは実際には単なるグローバル配列変数であり、ここで明らかに(できれば適切な)名前を付ける必要があります。Cではmyscript_parse_source()またはのように、関数名の前にカスタムプレフィックスを付加することにより、自分の関数を「名前空間」に配置するのが慣用的myscript_run_bytecode()です。カスタム名は、理想的には、それが属しているライブラリの名前を表すものとします。ここで混乱が生じます。

のバインディングを書いているとしましょうlibcURL。この場合、次のように拡張ライブラリを呼び出すのが合理的curl_myscript_bindingです。

MYSCRIPT_API const MyScriptExtFunc curl_myscript_lib[10];

しかし、これはcurl名前空間と衝突します。(私はそれを呼び出すことさえ考えましたcurlmyscript_libが、残念ながらlibcURLはcurl_プレフィックスのみを使用していません-パブリックAPIにはCURLCODE_*やなどのマクロが含まれているCURLOPT_*ため、これにより名前空間も乱雑になると思います。)

もう1つのオプションはmyscript_curl_lib、それをとして宣言することですが、バインディングを作成するのが私だけである場合にのみ有効です(自分の名前空間で何をしているのかわかっているため)。他のコントリビューターが独自のネイティブバインディングを追加し始めるとすぐに、myscript名前空間が乱雑になります。(私はいくつかの調査を行いましたが、たとえば、Perl cURLバインディングはこのパターンに従っているようです。それについて私が何を考えるべきかわかりません...)

では、変数に名前を付けるにはどうすればよいでしょうか。従うべき一般的なガイドラインはありますか?


3
グローバルの必要はありません。APIで関数を提供して新しい拡張を登録することもできます。たとえばSomeLang_register_extension("curl", "H2CO3", "000.001.000", the_extension)、where the_extensionは拡張構造を指しますが、グローバルには表示されません。言語は内部データ構造を保持し、名前、バージョン、作成者で拡張機能を並べ替えます。
アモン

@amon確かに、それも可能です。
H2CO3 2013年

この回答は興味深いかもしれません。別のテーマを扱いますが、HTMLの命名規則がどのように派生するかを説明しています。異なる言語にも同様の規則があります。ニーズに一致する規則を選択してそれに従うと便利な場合があります。
Rob

回答:


2

現実的には、ランタイム環境から見えるようにするためだけに、エクスポートされた関数のグローバル配列を含める必要はありません。

尋ねるべき良い質問は、ランタイム環境が関数ポインタとそれに関連付けられた名前を保存するかどうかです。

グローバル配列を使用して関数をエクスポートするという概念は、ランタイム環境がその情報を保存しない場合にのみ意味がありますが、VMの実行環境を適切に実行するには保存する必要があると思います。

あなたのようなスクリプト言語に追加される共通の機能は、関数登録するという考えです。

基本的に、エクスポートされた関数ptrと、スクリプトコードで使用されるエクスポートされた関数ポインターの名前を格納する媒体が必要です。

このために実装できる2つのオプションを知っています。

  1. スクリプト側の関数名を文字列キーとして使用し、関数ptrをそのキーに関連付けられた値として使用するハッシュマップ。

    exported_funcs["do_thing"] = &native_do_thing;

  2. Pawnなどの組み込みシステムスクリプト言語で一般的に使用されますが、スクリプトデータ自体を使用して関数ポインターを格納できます。関数を「登録」するときは、スクリプトのエクスポートされた関数テーブルを反復処理し、エクスポートされた関数が登録される名前を検索します。その名前を見つけたら、そのスクリプトデータ(スクリプトファイル自体ではなく、読み込まれたスクリプトメモリデータ)を上書きし、基本的にネイティブ関数ポインターを保存します。

FuncPtrType **table_entry = get_script_entry_ptr(func_name); *table_entry = func_ptr;

2番目のオプションについては、テーブルエントリにすべてのアーキテクチャのポインタサイズに対応できるだけの十分なサイズを与えることを強くお勧めします。特に、エントリは8バイトにする必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.