1

ネイティブとは、C++またはCで書かれたことを意味します

私はJavaをベースにしたプログラミング言語を作成しています。これには、VMとバイトコードコンパイラへの言語が含まれています。

ループ、変数、算術などの言語の機能を実装するforことは、私にとって問題ではありません。ただし、Javaのようなネイティブ関数を実行することは可能です。

私の言語で書かれたプログラムがウィンドウを作成し、ハードウェアやOSとインターフェイスし、単純な数学以外のことをすべて実行できるようにするために、ネイティブ関数が必要です。

JNIについて聞いたことがありますが、それは間違いなく私が望んでいることのように思えますが、そのようなものを実装する方法がわかりません。

私のVMはC++で実装されているので#include、コンパイル時にネイティブ関数のhppファイルを作成して、動的にロードすることができますdllso、これは実際には良い解決策とは思えません。別のネイティブ関数を実行できるようにするたびにVMを再コンパイルする必要があるためです。

問題はこれに帰着します:C ++プログラム(VM)が動的に(より正確にはバイトコードで指示された実行時に)C ++関数を使用してライブラリをロードし、ヘッダーで事前に宣言せずにそれらの関数を実行するにはどうすればよいですか?ファイル?

4

2 に答える 2

1

libffiを見てください。関数アドレスと呼び出しシグネチャを指定して、任意の関数を呼び出すメソッドを提供します。

その署名がどうあるべきかをどのように理解するかは、コンテキストによって異なります。引数の型に基づいて、さまざまな呼び出しを推測できます。 JNAは、明示的な Java インターフェイス、メソッド宣言、または動的呼び出し引数からネイティブ呼び出しシグネチャを推測します。

単純な関数呼び出しを超えて、コンストラクター、メモリ管理、およびオブジェクト メソッドのディスパッチを処理することはより複雑ですが、それでも同じ基本原則に基づいています。

于 2012-12-02T23:08:04.927 に答える
0

私がこれまでに説明したことのないトピックの1つは、新しい言語のVM関数呼び出しからC++スタックに引数を渡す方法とC++関数からの戻り値をVMに戻す方法です。

pow(3)関数を新しい言語で使用できるようにしたいとします。注意として、pow()署名は

double pow ( double base, double power )

最も簡単な方法は次のようなものです

void
language::pow( VM * pVM )
{
    double arg2 = pVM->PopDouble();
    double arg1 = pVM->PopDouble();
    double result = pow( arg1, arg2 );
    pVM->PushDouble( result );
}

しかし、それはあなたが求めているもののようには聞こえません。dlopen()とdlsym()を組み込むと、次のようになります。

void
language::pow( VM * pVM )
{
    double arg2 = pVM->PopDouble();
    double arg1 = pVM->PopDouble();
    void *handle = dlopen("libm", RTLD_LAZY);
    if (!handle) { /*...return; ...*/ }
    typedef double (* pfPow ) ( double, double );
    pfPow pPow = (pfPow) dlsym(handle, "pow");
    if (!pPow) { /*...return; ...*/ }
    double result = (* pPow )( arg1, arg2 );
    pVM->PushDouble( result );
}

しかし、それはさらに悪いことです。言語がアクセスできるようにするC++関数ごとにスタブ関数が必要です。

あなたの言語に次のようなものを持たせたいようです

double result = eval_double( "libm", "pow", arg1, arg2 );

それをC++で実装する方法がわかりません。Varagsは、任意のタイプのC++引数のフェッチをサポートしています。ただし、任意のタイプのC++引数をプッシュするためのAPIはありません。

于 2012-12-04T01:01:29.470 に答える