標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第470回]
●「外部シンボル …が未解決」
今回は、2ヶ月も前に書きました、[第432回]からの懸案でありました、「外部シンボル …が未解決」という意味不明のエラーがいよいよ、といいますか、やっと「解決」いたします。
わかっていらっしゃる方には、何てこともないようなエラーメッセージなのでしょうけれど、全然わかっていらっしゃらない私といたしましては、こういう意味不明のメッセージに直面すると、もうどこから手をつけていったらよいものか、途方に暮れてしまいます。
これが昔ですと、中区栄の丸善とか星野書店とかなどに足を運び(ああ。当地名古屋のお話です)、専門書のコーナーに入り浸りで片っ端から目次や索引をめくってまわる、ということになるのでありますが、今は有難い時代で、たいていのことはインターネットでけりがついてしまいます。
で、ネットで検索をして回りましたところ、なんとか見えてまいりました。
どうやら、この「未解決」というのは、そういう関数がみつからないよ、ということを意味しているらしいのですね。
うう。それなら、業界用語などをお使いにならないで、「みつからない」と直截におっしゃっていただきたいですう。
そんなわけのわからない業界用語をお使いになるものですから、パラメータがおかしいのか、とかまたWindowsのバージョンが違うのか、など悩まないでもよいところで悩んでしまって、何日も空費してしまうのでありますから…。
はなから、「みつからない」と言っていただければ、それはそれでいくらなんでもこれはおかしいぞ、ということで、それなりに調べ方もありますでしょうに。
だってincludeしておりますヘッダーファイルを調べましたら、ちゃんと定義してあるじゃありませんか。
Hidsdi.hの前半部分を以下に示します。
/*++ Copyright (c) 1996 Microsoft Corporation Module Name: HIDDLL.H Abstract: This module contains the PUBLIC definitions for the code that implements the HID dll. Environment: Kernel & user mode Revision History: Aug-96 : created by Kenneth Ray --*/ #ifndef _HIDSDI_H #define _HIDSDI_H #include <pshpack4.h> //#include "wtypes.h" //#include <windef.h> //#include <win32.h> //#include <basetyps.h> typedef LONG NTSTATUS; #include "hidusage.h" #include "hidpi.h" typedef struct _HIDD_CONFIGURATION { PVOID cookie; ULONG size; ULONG RingBufferSize; } HIDD_CONFIGURATION, *PHIDD_CONFIGURATION; typedef struct _HIDD_ATTRIBUTES { ULONG Size; // = sizeof (struct _HIDD_ATTRIBUTES) // // Vendor ids of this hid device // USHORT VendorID; USHORT ProductID; USHORT VersionNumber; // // Additional fields will be added to the end of this structure. // } HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; BOOLEAN __stdcall HidD_GetAttributes ( IN HANDLE HidDeviceObject, OUT PHIDD_ATTRIBUTES Attributes ); /*++ Routine Description: Fill in the given HIDD_ATTRIBUTES structure with the attributes of the given hid device. --*/ void __stdcall HidD_GetHidGuid ( OUT LPGUID HidGuid );
ほうらね。
HidD_GetHidGuidもHidD_GetAttributesもちゃんとあるじゃありませんか。
そうすると、これでも「みつからない」というからには、これは相当におかしい何かがあるに違いない、ということになります。
ということで、さらに追求を続けた結果、やっとのことで正解にたどりつきました。
●C++とCの違いが関係しているらしい
どうやらこれは、”C++”と”C”の「名前の解決」の違いが関係している、のだそうです。
それならそうと言ってくださいよお。
ますますCの眷属全てが嫌いになってしまうじゃありませんかあ。
つまるところ、どういういきさつかはわかりませんが、このHidsdi.hなるものが、C++ではなくて、Cで記述されているらしいのでありますね(あるいは、Hidpi.hも、か?)。
なんでもCでの関数名とC++の関数名は、ソースプログラムでは同じに見えていても、コンパイルすると違うものになってしまうのだそうで…(うむむ。なんともややこしい)。
で、もともとCで書かれたソースプログラム(ヘッダーファイル)をC++で書かれたプログラムと一緒にC++でコンパイルすると、そのヘッダーファイルの先にあるはずの、ライブラリファイル(DLLの情報がある)との間で名前の整合性がなくなってしまって、そんな関数名はみつからないよ、というエラーメッセージになってしまう、ということのようであります。
じゃあ、その始末はいったいどうしてくれるのか、といいますと、そこで登場しますのが、extern ”C”です。
●extern ”C”
これもなんだかよくわからないものなのでありますが、これを”C”で書かれた関数名の前につけておきますと、そのところはC++コンパイラが、”C++”の名前ルールではなくて、”C”の名前ルールでコンパイルしてくれるのだそうです。
むむむ。よくはわからないのですけれど、やってみなけりゃあしょうがないのでありますから、とりあえず、Hidsdi.hの、
void __stdcall
HidD_GetHidGuid (
のところを、
extern "C" void __stdcall HidD_GetHidGuid (
のように直して、コンパイルしてみました。
そうしましたら。
おお。
そのようにHidsdi.hを直す前は、
Error:外部シンボル…
というのが2つ表示されていたところが、直したあとでは、エラーが1つになりました。
画面の真中から下のあたりで実行しているコンパイルでは、
HidD_GetHidGuid(
の前にextern ”C”を追加した、Hidsdi.hを作業中のフォルダに置いたあとでコンパイルしています。
HidD_GetHidGuid( については、エラーが出なくなりました。
これで、やっと「解決」です。
Hidsdi.hに定義されている全ての関数の前に
extern ”C”
をつければ、この問題は解決いたします。
やっとのことで、めでたし、めでたし、です。
しかし。
それはそれでよいのですけれど、全ての関数の前にextern ”C”をつける、というところが、
うむむ。
少しばかり面白くないなあ、という気がします。
で、もう少し調べてみましたら、こういう書き方もできることがわかりました。
(これより前の部分省略) Revision History: Aug-96 : created by Kenneth Ray --*/ #ifdef __cplusplus extern "C" { #endif #ifndef _HIDSDI_H #define _HIDSDI_H (この間省略) #ifdef __cplusplus } #endif
つまり、もしC++でコンパイルするならば、このソースプログラムの、その位置に
extern ”C” {
を置いて、そしてソースプログラムの最後のところにも、もしC++でコンパイルするならば、最後のその位置に
}
を置きますよ、ということです。
Hidsdi.hにそのようにして書き加えたものをHidsdi2.hとして作業中のフォルダに置き、そしてテストプログラムHidtest1_8_d.cppの、
#include "hidsdi.h"
を
#include "hidsdi2.h"
に直してから、コンパイルしてみました。
おお。エラーは出なくなりました。
うう。
しかし。
最初は、ちょいとかっこいい、と思った、
#ifdef __cplusplus
ですけれど、よくよく考えてみると、それもなんだか回りくどいのではないですかあ。
「もしも」、も何も、私ははじめからC++を使うつもりなので、そのほかの言語を使うつもりはさらさらありませんから、この #ifdef
__cplusplus は全く余計な気がします。
それならば、いっそ、こんな具合にできませんかねえ。
Hidsdi.hはもとの最初のままのものを使うことにしまして、HIDテストプログラムの、
#include "hidsdi.h"
のところを、
extern "C" { #include "hidsdi.h" }
にしてみました。
HIDテストプログラムのソースリストは[第431回]にあります(そのリストでは、#include "hidsdi2.h" になっています)。
これをHidtest1_8_e.cppという名前にしたうえで、コンパイルしてみました。
おお。どうやらエラーにならずにうまく通ったようです。
これなら、文句無し、です。
めでたし、めでたし、でした。
2010.4.5upload
前へ
次へ
ホームページトップへ戻る