8

レガシ Visual C++ 6 アプリの修正で行き詰まっています。私が入れたC++ DLLソースで

extern "C" _declspec(dllexport) char* MyNewVariable = 0;

その結果、(dumpbin /exports blah.dll で示されるように) エクスポート テーブルに MyNewVariable が (きれいに装飾されずに) 表示されます。しかし、C ソース ファイルでアクセスできるように変数を宣言する方法がわかりません。私はさまざまなことを試しました。

_declspec(dllimport) char* MyNewVariable;

しかし、それは私にリンカエラーを与えます:

未解決の外部シンボル "__declspec(dllimport) char * MyNewVariable" (__imp_?MyNewVariable@@3PADA)

extern "C" _declspec(dllimport) char* MyNewVariable;

トニーが示唆したように(そして私が以前に試したように)、予想される装飾が異なりますが、まだ削除されていません:

未解決の外部シンボル __imp__MyNewVariable

C アプリから C++ DLL 変数にアクセスできるように宣言を作成するにはどうすればよいですか?


答え

botismarius やその他の方々 (皆さんに感謝します) が特定したように、DLL の .lib とリンクする必要がありました。名前が壊れないようにするために、(C ソースで) デコレーターなしで宣言する必要がありました。つまり、.lib ファイルを使用する必要がありました。

4

7 に答える 7

5

DLL のコンパイル後に生成された lib に対してリンクする必要があります。プロジェクトのリンカー オプションで、ファイルを追加する必要があり.libます。はい、変数を次のように宣言する必要もあります。

extern "C" { declspec(dllimport) char MyNewVariable; }
于 2008-09-11T13:22:07.170 に答える
4

extern "C" は装飾を削除する方法です - 使用するとうまくいくはずです:

extern "C" declspec(dllimport) char MyNewVariable;

または、C++ または C で使用できるヘッダーが必要な場合 (/TC スイッチを使用)

#ifdef __cplusplus
extern "C" {
#endif
declspec(dllimport) char MyNewVariable;
#ifdef __cplusplus
}
#endif

そしてもちろん、エクスポートを行う dll によって生成されたインポート ライブラリとリンクします。

于 2008-09-11T13:20:37.003 に答える
3

ボティスマリウスをダウンモッドしたのが誰なのかはわかりません。彼は正しいからです。その理由は、生成された .lib が、外部変数/関数を簡単に宣言して__declspec(dllimport)使用できるようにするインポート ライブラリであるためです。インポート ライブラリは、必要な呼び出しを単純に自動化しLoadLibrary()ますGetProcAddress()。それがなければ、これらを手動で呼び出す必要があります。

于 2008-09-11T13:34:55.113 に答える
1

どちらも正しいです。エラーメッセージに記載されている__imp_?MyNewVariable@@3PADAということは、装飾された名前を探していることを意味するため、extern "C" が必要です。ただし、インポート ライブラリとのリンク必要です。そうしないと、別のリンク エラーが発生するだけです。

于 2008-09-11T13:36:46.217 に答える
1

@Graeme: その通りです。OPが使用している「C」コンパイラは、C99標準を強制しているのではなく、C++としてコンパイルしているため、名前がマングリングされていると思います。extern "C"真の C コンパイラは、キーワードの「C」の部分を理解できません。

于 2008-09-11T13:40:44.443 に答える
1

dll ソース コードでは、.lib ファイルがシンボルをエクスポートするように、次の実装が必要です。

extern "C" _declspec(dllexport) char* MyNewVariable = 0;

C クライアントは、クライアント コードがシンボルをインポートするように、この宣言でヘッダーを使用する必要があります。

extern "C" _declspec(dllimport) char* MyNewVariable;

このヘッダーは、dll ソース コードに #include するとコンパイル エラーが発生するため、通常は、エクスポートされた関数およびクライアントによってのみ使用されるエクスポート ヘッダーに配置されます。

必要に応じて、次のようにどこにでも含めることができる「ユニバーサル」ヘッダーを作成することもできます。

#ifdef __cplusplus
extern "C" {
#endif
#ifdef dll_source_file
#define EXPORTED declspec(dllexport) 
#else
#define EXPORTED declspec(dllimport) 
#endif dll_source_file
#ifdef __cplusplus
}
#endif

EXPORTED char* MyNewVariable;

次に、dll ソース コードは次のようになります。

#define dll_source_code 
#include "universal_header.h"

EXPORTED char* MyNewVariable = 0;

クライアントは次のようになります。

#include "universal_header.h"
...
MyNewVariable = "Hello, world";

これを何度も行うと、上部のモンスター #ifdef が export_magic.h に入り、universal_header.h が次のようになります。

#include "export_magic.h"

EXPORTED char *MyNewVariable;
于 2008-09-11T16:37:08.823 に答える
0

Windows でプログラミングしていたときに _declspec(dllimport) を使用したことはありません。単純に宣言できるはずです

extern "C" char* MyNewVariable;

DLL のコンパイル時に作成された .libb にリンクします。

于 2008-09-11T14:17:44.790 に答える