2009-08-27 22 views
1

VC++のコンパイラでラッパーライブラリを構築しようとしています。未解決の外部シンボルエラーで混乱しました

cl /I%ERL_DRIVER_H% /LD /MD ErlDriver.c 

あるbuild.bat

ErlDriver.c

#define __WIN32__ 
#define DLL_EXPORT __declspec(dllexport) 

#include "erl_driver.h" 

DLL_EXPORT int _driver_output(ErlDrvPort port, char *buf, int len) { 
    return driver_output(port, buf, len); 
} 

私はこれを構築しようとすると、私は、次のリンカエラーを取得:

ErlDriver.obj : error LNK2019: unresolved external symbol _WinDynDriverCallbacks referenced in function __driver_output

をerl_win_dyn_driver.herl_driver.hに含まれる)

typedef struct { 
    WDD_FTYPE(driver_output) *driver_output; 
    // a ton more of those 
} TWinDynDriverCallbacks; 

extern TWinDynDriverCallbacks WinDynDriverCallbacks; 

#define driver_output (WinDynDriverCallbacks.driver_output) 

あなたが見ることができるように、WinDynDriverCallbacksはが宣言定義さ です。

リンカエラーの原因は何ですか?

答えて

1

「宣言する」とCやC++で「定義する」の間には微妙な違いがあります。宣言すると、特定のシンボルが他のどこかで定義されることをコンパイラに通知します。これにより、実際の定義を参照する必要なしにシンボルがそのシンボルを使用できるようになります。リンクされているコードのどこかにシンボルを定義する必要があります。そうしないと、表示されているエラーメッセージが表示されます。

例えば、これはシンボルWinDynDriverCallbacksの宣言です:

extern TWinDynDriverCallbacks WinDynDriverCallbacks; 

あなたのコードは、この宣言がある - それは成功した(リンクではなく)コンパイルに記号を使用するコードを可能にします。

あなたはどこかの定義を追加する必要があります。

TWinDynDriverCallbacks WinDynDriverCallbacks; 

定義は(ない一般ヘッダファイルで)どこかにソースコードファイルに行かなければなりません。これは、そのオブジェクトのオブジェクトコードに領域を割り当てるようにコンパイラに指示し、プログラムが正常にリンクできるようにします。

+0

私はそれがなぜ機能するのか全く分かりませんが、確かにあります。なぜ私はそれを使用する必要はありません私が見つけることができるすべてのErlangポートドライバは何ですか? –

+0

リンカは定義を必要としないように、同等のものを実行している必要があります。そうでないと、リンカは定義を必要としません。 –

+0

リンクを必要とする.libファイルがあります。あなたが使用しているSDKの一部であるかもしれません –

2

いいえ、定義されていません(少なくともあなたが引用したものは)。それは宣言されています。 "extern"キーワードは、 "このシンボルの定義は別のコンパイル単位(ソースファイル)に表示されます"を意味します。シンボルを定義するソースファイルをコンパイルして生成されたオブジェクトファイル(またはライブラリ)とリンクする必要があります。

+0

オブジェクトファイルまたはライブラリがありません。私が持っているのはヘッダーファイルだけです。私が行っている指示はlibsとリンクしていません。 –

+0

ヘッダーファイルには変数またはコードが含まれていません。それらは宣言だけを含んでいます。 "ヘッダファイル"だけでは何もできません。指示が間違っているか、誤解しています。 –

+0

私は、Driverという言葉が現れ続けていることに気付きました。 Windowsデバイスドライバを構築しようとしていますか?もしそうなら、シンボルはWindowsカーネル内にあるかもしれません.Windowsドライバを書くことについてもっと知っている人は、あなたが望むものを達成する方法についてコメントすることができます。 –

1

WindowsでNIFを構築するのと非常によく似た問題が発生しました。未解決の外部シンボル_WinDynNifCallbacks。これがERL_NIF_INITマクロによって定義されていることがわかります。私のケースでは、マクロ全体をextern Cブロックに囲む必要がありました。これは、私は強く、この問題は、同じ問題が原因であるが、アーランポートドライバのDRIVER_INITマクロを疑う

extern "C" 
{ 
    ERL_NIF_INIT(...) 
} 

を成功している間、このすなわち

extern "C" ERL_NIF_INIT(...) 

に失敗しました。

0

Driver_Initは、 "TWinDynDriverCallbacks WinDynDriverCallbacks;"を宣言するメインループです。 driver_initを定義する複数の行で正しく宣言されています。それをextern "c"で囲む必要はありません。

私のベアボーンをセットアップしようとしている間にこのスレッドが約100万回出てきたので、erlangポートドライバはここでこれを言うでしょう。私はジョー・アームストロングのプログラミング・エルラン・ブックの第12章インターフェース技術から取り組んでいます。 erl5.9とvs2010を使用しています。

本のコードでは、example1_lib.cに抜けていてエラーがありました。このエラーは、書籍のバージョンとerlangのバージョンの変更に起因する可能性が最も高いですが、

example1_lib.cの一番上に(#define WIN32)を設定する必要があります。そうでない場合、erlangはすべてのLinuxオプションにデフォルト設定されます。

(int bufflen)から(ErlDrvSizeT bufflen)をexample_drv_outputに変更する必要があります。

その後、きれいにしました。

関連する問題