3

関数名で「動的に」関数ポインターを取得するCプログラムがあります(つまり、関数名を文字列として渡し、関数へのポインターを取得します)。私はすでにdlopenとdlsymを使用してLinuxでこれを行っており、dlfcnを使用した他のUnixライクでも機能すると思います。

MinGWを使用してこのプログラムをWindowsに移植しようとしたときに、問題が発生しました。「GetProcAddress(handle、symbol_name)」を使用して名前を検索しようとすると、「symbol_name」はコールバック関数の名前であり、「handle」は「GetModuleHandle(NULL)」によって返される現在の実行可能ファイルへのハンドルです。何も取得されません。 MinGWの名前マングリングは、シンボル名に「_」を追加するためです。

明らかな解決策(必要な記号の前に「_」を付ける)は、移植性にとって少し「危険」に思えます(コンパイラーがそれらのいくつかに2つのアンダースコアを追加する可能性がありますか?わかりません)。

  • コンパイラが私のシンボルに名前を付けないようにするためのより良い方法はありますか?(またはそれらのサブセット、動的に検索する必要があるコールバックのみ);

  • または、GetProcAddressに、マングルされた場合でもそれらを検出させる方法はありますか?

オプション-fno-leading-underscoreも試しましたが、すべての外部シンボルのマングリングも削除され、プログラムをstdlibなどとリンクできなくなりました(また、ドキュメントの警告は少し怖いです)。

また、純粋なCを使用していることに注意してください(コードのどの部分にもC ++はありません)。また、すべてのコードは単一の「.exe」に含まれています。

TIA

4

2 に答える 2

0

考えられる最も単純なDLLの例では再現できないため、問題が何であるかわかりません。

/* hello_dll.c */
#include <stdio.h>

__declspec(dllexport) void hello ( void )
{
    puts ( "Hello, DLL!");
}

/* hello_exe.c */
#include <windows.h>
#include <stdio.h>  

int main () {
    typedef void (*pfunc)(void);

    HANDLE hself;

    pfunc hello;

    hself = GetModuleHandle(NULL);

    hello = (pfunc)GetProcAddress(hdll, "hello");

    hello();

    return 0;
}

これは、特別なフラグなしで MinGW gcc を使用するコマンド ラインであり、すべて動作します。

gcc src\hello_dll.c src\hello_exe.c -o bin\hello.exe
$ bin\hello.exe
Hello, DLL!
$ gcc --version
gcc (GCC) 4.5.0

__declspec(dllexport)自分から関数を取得している場合、それなしでは機能しません。DLL を作成するgcc -shared場合は不要のようですが、exe から関数をエクスポートする場合は必要と思われます。

于 2011-02-12T18:36:01.970 に答える
0

C は名前マングリングを使用しません。特に、名前に型情報を追加しません (C++ とは異なります)。ただし、一部のプラットフォームでは、アンダースコアを前に付けるなど、名前に小さな変更を加えています。また、C++ とは異なり、プラットフォーム固有であり、コンパイラ固有ではありません。

これまでに見たすべてのプラットフォームで、変更がないか、先頭のアンダースコアしか見たことがありません。

したがって、現在のプラットフォームがアンダースコアを使用しているかどうかを判断するために、いくつかのifdefを使用することをお勧めします。

(Windows には、ANSI バージョンと Unicode バージョンを区別するために、特定の Windows API 関数に別の小さな変更があります。しかし、それはおそらくあなたのケースには関係ありません。)

他の誰かが、さまざまなプラットフォームでの C ABI の公式ドキュメントを指摘できるかもしれません。

于 2011-02-12T18:36:41.287 に答える