VC PlusPlus:Link Error LINK2019 未解決のシンボル…で参照されました。 対処方法 新しいページはコチラ

提供: yonewiki
移動: 案内, 検索
(2.C言語とC++言語の混在による呼び出し関数の互い違い)
(知っていた方が良い小技)
 
49行: 49行:
  
 
 以下のようなコマンドを打つと生成できます。必ずしも出力できるわけではありません。dllを生成したプログラム側で__declspec(dllexport)というような宣言をしてあるものに限ります。
 
 以下のようなコマンドを打つと生成できます。必ずしも出力できるわけではありません。dllを生成したプログラム側で__declspec(dllexport)というような宣言をしてあるものに限ります。
 +
 +
 defファイルの中身は自動で適切に生成されることもありますが、以下のような形式に整理しないといけない場合もあります。
 +
 +
以下はwintab32.dllっていうファイルから作ったdefファイルの抜粋です。
 +
<syntaxhighlight2 lang="text">
 +
Dump of file wintab32.dll
 +
 +
File Type: DLL
 +
 +
  Section contains the following exports for Wintab32.dll
 +
 +
    00000000 characteristics
 +
    59BBE69A time date stamp Fri Sep 15 23:41:30 2017
 +
        0.00 version
 +
          20 ordinal base
 +
        1184 number of functions
 +
          54 number of names
 +
 +
    ordinal hint RVA      name
 +
 +
        25    0 000079E1 Sync
 +
        22    1 00006235 WTClose
 +
        60    2 000089CC WTConfig
 +
        81    3 000033C3 WTDataGet
 +
        (省略)
 +
</syntaxhighlight2>
 +
 +
というように吐き出された時のname欄が関数名でSyncとかWTCloseってのがソレにあたる。関数名には@が入ったりもします。
 +
 +
<syntaxhighlight2 lang="text">
 +
LIBRARY (ファイル名(拡張子を省く))
 +
EXPORTS
 +
        (関数名)
 +
        (関数名)
 +
        (関数名)
 +
        (関数名)
 +
</syntaxhighlight2>
 +
 +
 コマンドは
 
<syntaxhighlight2 lang="bash">
 
<syntaxhighlight2 lang="bash">
 
dumpbin.exe /EXPORT (DLLライブラリファイル名or(完全パスor相対パス)\DLLライブラリファイル名) > (ライブラリ名と同じ名前).def
 
dumpbin.exe /EXPORT (DLLライブラリファイル名or(完全パスor相対パス)\DLLライブラリファイル名) > (ライブラリ名と同じ名前).def
123行: 162行:
  
  
 かなり、わけわからん@@とかYXPAとかどっから来たん?ってなると思います。そもそもマングリングってなんかヤラシイ名前で恥ずかしい(Embarrass)わ。とか言っている日本人のなんと多いことか。チコちゃんはしっています。マングリングとは!
+
 かなり、わけわからん@@とかYXPAとかどっから来たん?ってなると思います。そもそもマングリングってなんかヤラシイ名前で恥ずかしい(Embarrass)わ。とか言っている日本人のなんと多いことか。そうです。チコちゃんはマングリングが何なのかしっています。
  
  
129行: 168行:
  
  
 装飾。英語のmanglingは日本語で修飾という意味です。マングリ返しとは関係ないし、ペロペロしたりもしません。チコちゃんは5歳なのにC++のマングリングまで知っているなんて、マングリ返しでもされたことをあるがかなぁ?「ませてはいませんて」そうなんです。C++では同一の関数名を名前空間を変更することによって定義できます。namespase ですね。だったり、オーバーロードという多重定義によって、引数が違うだけの関数名との切り分けも考慮した命名規則があります。命名規則は別の場所で解説するとして、元の名前がきちんとわかるようにわかりにくく修飾されています。元の名前は以下のようなundnameコマンドで確認できます。
+
 装飾。英語のmanglingは日本語で修飾という意味です。マングリ返しとは関係ないし、ペロペロしたりもしません。チコちゃんは5歳なのにC++のマングリングまで知っているなんて、マングリ返しでもされたことをあるのかなぁ?「ませてはいませんて」そうなんです。C++では同一の関数名を名前空間を変更することによって定義できます。namespase ですね。だったり、オーバーロードという多重定義によって、引数が違うだけの関数名との切り分けも考慮した命名規則があります。命名規則は別の場所で解説するとして、元の名前がきちんとわかるようにわかりにくく修飾されています。元の名前は以下のようなundnameコマンドで確認できます。
  
 
<syntaxhighlight2 lang="text">
 
<syntaxhighlight2 lang="text">
151行: 190行:
 
#endif
 
#endif
  
void __cdecl zcalloc(void * vValue,unsigned int uiValue,unsigned int uiValue2);
+
void __cdecl zcalloc(void * vValue, unsigned int uiValue, unsigned int uiValue2);
  
 
#ifdef __cplusplus
 
#ifdef __cplusplus
158行: 197行:
 
</syntaxhighlight2>
 
</syntaxhighlight2>
  
 のように記述することでC++言語を使っている場合にC言語の関数形式に必ず変更するという定義が出来ます。まぁC言語に対応するとか、割かし難しい場合もあります。
+
 のように記述することでC++言語を使っている場合にC言語の関数形式に必ず変更するという定義が出来ます。まぁC言語に対応するとか、割かし難しい場合もあります。__cdeclキーワードは、dllに関数を書き出す時に必要になるもので、libファイルにはすべてが書き出されます。
  
  
165行: 204行:
  
 
 そしてSample.hとSample.cppを自分が開発を進めているプロジェクトに取り込みます。インクルードパスの解決をしている場合は、Sample.hはプロジェクトに追加する必要はないかもしれません。なのでしっかりとSample.cppをプロジェクトに追加します。ヘッダファイルはSample.cpp内で#include "Sample.h"となっているなら、プロジェクトのプロパティのC/C++の項目の全般のところにある追加のインクルードファイルパスにSample.hがあるところを相対パスで指定します。必ずセットで移動する仕組みの関係になっていればです。一緒には動かさない。参照するライブラリ群は常に同じなら絶体パスで指定すると良いでしょう。であれば、本来ならばインクルードは#include <Sample.h>のように記述する方法をとるといいのかもしれません。元のファイルとの関係もあるので、あまり変更しない方がいいと思うので、"Sample.h"のような記述でインクルードするもの有りだとは思います。ちなみに<Sample.h>のようになっていれば、プロジェクトのプロパティのVCディレクトリという欄の追加のインクルードの方にパスを記述します。リンカエラーが何が参照できなかったかというヒントは表示されるので名前マングリング処理されたエラーが表示されても冷静に対処できるはずです。名前マングリングがややこしさを増殖させて感じてしまいがちですが、名前マングリングが起こることが分かっていれば、正確に何がどこに無くてエラーなのかっていうのは探知できると思います。
 
 そしてSample.hとSample.cppを自分が開発を進めているプロジェクトに取り込みます。インクルードパスの解決をしている場合は、Sample.hはプロジェクトに追加する必要はないかもしれません。なのでしっかりとSample.cppをプロジェクトに追加します。ヘッダファイルはSample.cpp内で#include "Sample.h"となっているなら、プロジェクトのプロパティのC/C++の項目の全般のところにある追加のインクルードファイルパスにSample.hがあるところを相対パスで指定します。必ずセットで移動する仕組みの関係になっていればです。一緒には動かさない。参照するライブラリ群は常に同じなら絶体パスで指定すると良いでしょう。であれば、本来ならばインクルードは#include <Sample.h>のように記述する方法をとるといいのかもしれません。元のファイルとの関係もあるので、あまり変更しない方がいいと思うので、"Sample.h"のような記述でインクルードするもの有りだとは思います。ちなみに<Sample.h>のようになっていれば、プロジェクトのプロパティのVCディレクトリという欄の追加のインクルードの方にパスを記述します。リンカエラーが何が参照できなかったかというヒントは表示されるので名前マングリング処理されたエラーが表示されても冷静に対処できるはずです。名前マングリングがややこしさを増殖させて感じてしまいがちですが、名前マングリングが起こることが分かっていれば、正確に何がどこに無くてエラーなのかっていうのは探知できると思います。
 +
 +
 +
 C言語からC++言語に変更するには、ファイルの拡張子の変更だけで済む場合もありますが、関数の引数の型定義が、外出しになっている以下のように記述された関数
 +
 +
Sample.c
 +
<syntaxhighlight2 lang="c">
 +
 +
void zcalloc(vValue, uiValue, uiValue2)
 +
void * vValue,
 +
unsigned int uiValue,
 +
unsigned int uiValue2
 +
{
 +
  …
 +
}
 +
</syntaxhighlight2>
 +
 を
 +
 +
Sample.cpp
 +
<syntaxhighlight2 lang="cpp">
 +
 +
void zcalloc(void * vValue, unsigned int uiValue, unsigned int uiValue2)
 +
{
 +
  …
 +
}
 +
</syntaxhighlight2>
 +
 と、こんな感じに修正する必要があります。メンドクサイ。
  
  

2021年8月21日 (土) 00:00時点における最新版



個人用ツール
名前空間

変種
操作
案内
ツールボックス