ページ 11

外部シンボル"~~"は未解決です。というのは何なのでしょうか?

Posted: 2011年9月04日(日) 04:19
by jun
たびたび書き込んでしまってすみません;
今回わかりやすいようにと思い、ファイルを分けてコンパイルしようとしたのですが、

1>------ ビルド開始: プロジェクト: VsActionShooting, 構成: Debug Win32 ------
1>load.obj : error LNK2001: 外部シンボル ""int tama" (?tama@@3HA)" は未解決です。
1>load.obj : error LNK2001: 外部シンボル ""int (* image2)[16]" (?image2@@3PAY0BA@HA)" は未解決です。
1>main.obj : error LNK2001: 外部シンボル ""int (* image2)[16]" (?image2@@3PAY0BA@HA)" は未解決です。
1>load.obj : error LNK2001: 外部シンボル ""int (* image1)[16]" (?image1@@3PAY0BA@HA)" は未解決です。
1>main.obj : error LNK2019: 未解決の外部シンボル "int (* image1)[16]" (?image1@@3PAY0BA@HA) が関数 _WinMain@16 で参照されました。
1>C:\Documents and Settings\*****\デスクトップ\対戦アクションシューティング\VsActionShooting\Debug\VsActionShooting.exe : fatal error LNK1120: 外部参照 3 が未解決です。
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========

という文字が最後に出てきてしまいました。
これはどういう意味のものなのでしょうか?
解決策も教えてくださるとありがたいです。

Re: 外部シンボル"~~"は未解決です。というのは何なのでしょうか?

Posted: 2011年9月04日(日) 05:37
by box
使おうとしているが定義していない変数がある、ということでありましょう。
とりあえず、
main.c(あるいはmain.cpp)
load.c(あるいはload.cpp)
の2つのソースコードを見せてください。

Re: 外部シンボル"~~"は未解決です。というのは何なのでしょうか?

Posted: 2011年9月04日(日) 05:41
by うしお
変数、および関数等には、「宣言」と「定義」という考え方があります。

宣言とは、コンパイラに対して、どこかのソースファイルにこんな変数(また関数等)があるよ、と教えるだけです。
定義とは、コンパイラに対して、実際に変数(また関数等)の作成を依頼することです。

宣言は何回でも行えますが、
定義は全ソースファイルで唯一である必要があります。(かぶったら同じ名前の変数を区別する手段がなくなりますよね)
宣言は主にヘッダで行い、定義はソースファイルで行うことが多いですね。

例えば宣言は以下のようにします。

コード:

extern int tama;//変数の宣言
int func();//関数の宣言
これに対して

コード:

int tama;
int func()
{
  return 0;
}
と書きますと、これは「定義」+「宣言」を指示したことになります。
 (定義だけ行うことは出来ませんし、できるメリットもありません)

ビルドはコンパイル→リンクの手順で行いますが、
コンパイラは、リンク時に宣言と定義を結びつけます。これを「外部シンボルの解決」といいます。
つまり、外部シンボルは未解決とは、
「宣言されてるけど、どこにも定義がみつからないよ!」
というコンパイラの悲痛な叫びなわけです。

したがって今回のケースでは、
extern int tama;
extern int (* image2)[16];
と宣言だけ行って定義をし忘れている、またはスペルが間違っている 可能性を疑ってみるべきでしょう。

例えば下のようなマクロを書いて、#define GLOBAL_VALUE_DEFINEを書き忘れている、等はありませんか?
(普通にexternで書いたほうが分かりやすいと思いますが)

コード:

#ifdef GLOBAL_VALUE_DEFINE
#define GLOBAL
#else
#define GLOBAL extern
#endif

Re: 外部シンボル"~~"は未解決です。というのは何なのでしょうか?

Posted: 2011年9月04日(日) 11:24
by softya(ソフト屋)
ファイル分割の仕組みはこちらを読んでみてください。

「新・C言語 ~ゲームプログラミングの館~ [DXライブラリ]」
http://dixq.net/g/
d.1 メイン関数の作り方
d.2 複数のファイルにわけてコンパイルする
d.3 ゲームの設計と分割コンパイル(1)
d.4 ゲームの設計と分割コンパイル(2)
d.5 ゲームの設計と分割コンパイル(3)

Re: 外部シンボル"~~"は未解決です。というのは何なのでしょうか?

Posted: 2011年9月05日(月) 03:05
by jun
#define GLOBAL_VALUE_DEFINEが抜けていたので、追加しました。

次は

1>------ ビルド開始: プロジェクト: VsActionShooting, 構成: Debug Win32 ------
1> load.cpp
1>c:\documents and settings\*****\デスクトップ\対戦アクションシューティング\vsactionshooting\load.cpp(5): error C2664: 'DxLib::LoadDivGraph' : 7 番目の引数を 'int' から 'int *' に変換できません。(新しい機能 ; ヘルプを参照)
1> 整数型からポインター型への変換には reinterpret_cast、C スタイル キャストまたは関数スタイル キャストが必要です。
1>c:\documents and settings\*****\デスクトップ\対戦アクションシューティング\vsactionshooting\load.cpp(6): error C2664: 'DxLib::LoadDivGraph' : 7 番目の引数を 'int' から 'int *' に変換できません。(新しい機能 ; ヘルプを参照)
1> 整数型からポインター型への変換には reinterpret_cast、C スタイル キャストまたは関数スタイル キャストが必要です。
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========

とでてしまいました;;

とりあえず、main.cpp,GV.h,load.cppを貼ってみます。
GVやloadは龍神録を見ながら作りました。
まだいろいろとやっていないところがあるので、main.cppはごちゃごちゃしています;

○main.cpp

コード:

#include "DxLib.h"
#include "GV.h"
#include "struct.h"
 
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
 
    int tama = 0;
 
    int tamaflag1p = 0;
    int tamaflag2p = 0;
	
	//構造体変数宣言
	ch_1 ch1;
	ch_2 ch2;

	
    char Key[256];
 
    if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //ウィンドウ化と初期化処理
 
    //1p 場所
    ch1.x    =120;
    ch1.y    =240;
    //2p 場所
    ch2.x    =480;
    ch2.y    =240;
 
 
    SetDrawScreen( DX_SCREEN_BACK ) ;  //描画先を裏画面に設定
	
	load();


    while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
            //↑メッセージ処理        ↑画面をクリア         ↑キーボード入力状態取得       ↑ESCが押されると終了
 
        
        
//================================================
//      操作
//================================================
 
        ////////////////
        /// player 1 ///
        ////////////////
        if( Key[ KEY_INPUT_D ]  == 1 ){     //右
            ch1.x += 2.0f ;
        }
 
        if( Key[ KEY_INPUT_A ]  == 1 ){      //左
            ch1.x -= 2.0f ;
        }
 
        if( Key[ KEY_INPUT_S ]  == 1 ){      //下
            ch1.y += 2.0f ;
        }
 
        if( Key[ KEY_INPUT_W ]  == 1 ){      //上
            ch1.y -= 2.0f ;
        }
 
        if( Key[ KEY_INPUT_G ]  == 1 ){
            tamaflag1p = 1;
        }
       

                
        ////////////////
        /// player 2 ///
        ////////////////
        if( Key[ KEY_INPUT_RIGHT ]  == 1 ){      //右
            ch2.x += 2.0f ;                
        }
 
        if( Key[ KEY_INPUT_LEFT  ]  == 1 ){     //左
            ch2.x -= 2.0f ;                
        }
 
        if( Key[ KEY_INPUT_DOWN  ]  == 1 ){      //下
            ch2.y += 2.0f ;                
        }
 
        if( Key[ KEY_INPUT_UP    ]  == 1 ){      //上
            ch2.y -= 2.0f ;  
        }
 
        if( Key[ KEY_INPUT_SPACE ]  == 1 ){
            tamaflag2p = 1;
        }


 
//=========================================================
//=========================================================
 
//=======================================================
//          画像描画
//=======================================================
		//p1
		DrawGraph( ch1.x , ch1.y ,image1[14], TRUE  ) ;
		//p2
		DrawGraph( ch2.x , ch2.y ,image2[4], TRUE  ) ;

	

//=======================================================
//=======================================================
        ScreenFlip();//裏画面を表画面に反映
    }
 
    DxLib_End();
    return 0;
}


○load.cpp

コード:

#include "GV.h"

void load(){
	
    LoadDivGraph( "picture/char.png" , 16 , 4 , 4 , 32 , 32 , image1[16] ) ;//画像を分割してimage配列に保存
    LoadDivGraph( "picture/char2.png" , 16 , 4 , 4 , 32 , 32 , image2[16] ) ;//画像を分割してimage配列に保存
    
	tama = LoadGraph( "picture/tama.png");

}


○GV.h

コード:

#include "DxLib.h"
#include "math.h"



#ifdef GLOBAL_VALUE_DEFINE
#define GLOBAL_VALUE_DEFINE
#define GLOBAL
#else
#define GLOBAL extern 
#endif

#include "function.h"


//画像用変数宣言
GLOBAL int image1[16]; //p1
GLOBAL int image2[16]; //p2
GLOBAL int tama;	   //弾



長文失礼しました。

Re: 外部シンボル"~~"は未解決です。というのは何なのでしょうか?

Posted: 2011年9月05日(月) 08:58
by softya(ソフト屋)
LoadDivGraphの使い方が間違っていますね。
http://homepage2.nifty.com/natupaji/DxL ... .html#R3N3

あと私の紹介したDixq(管理人)さんの新しい分割に沿ったほうが良いでしょう。
龍神録のファイル分割の仕組みは、あまり良くないとご本人も仰ってますし。私もそう思います。

「新・C言語 ~ゲームプログラミングの館~ [DXライブラリ]」
http://dixq.net/g/
d.1 メイン関数の作り方
d.2 複数のファイルにわけてコンパイルする
d.3 ゲームの設計と分割コンパイル(1)
d.4 ゲームの設計と分割コンパイル(2)
d.5 ゲームの設計と分割コンパイル(3)

Re: 外部シンボル"~~"は未解決です。というのは何なのでしょうか?

Posted: 2011年9月07日(水) 02:52
by jun
softyaさんが言ったとおりLoadDivGraphを直したらできました!

あと、

d.1 メイン関数の作り方
d.2 複数のファイルにわけてコンパイルする
d.3 ゲームの設計と分割コンパイル(1)
d.4 ゲームの設計と分割コンパイル(2)
d.5 ゲームの設計と分割コンパイル(3)

を参考にしたら、自分でもものすごくわかりやすいモノになりました!

答えてくれた皆さんありがとうございました!
また、わからないことがあったら質問するかもしれないので、そのときはよろしくお願いします!!