2011-01-15 25 views
3

ここ数日間は、私が取り組んでいるCLIゲームプロジェクトのファイルをリンクする方法を見つけようとしています。プロジェクトの2つの部分、クライアントコードとサーバーコードがあります。(C++)名前空間とリンクすると重複シンボルエラーが発生する

クライアントには2つのライブラリが必要です。最初のものは汎用ゲームボードです。これはGameEngine.hとGameEngine.cppに分かれています。ヘッダファイルには、この

namespace gfdGaming { 

// struct sqr_size { 
//  Index x; 
//  Index y; 
// }; 
    typedef struct { Index x, y; } sqr_size; 
    const sqr_size sPos = {1, 1}; 
    sqr_size sqr(Index x, Index y); 
    sqr_size ePos; 
    class board 
    { 
    // Prototypes/declarations for the class 
    } 
} 

そしてCPPファイルのようなものがちょうどコンテンツのすべてを与えているに見えます

#include "GameEngine.h" 

type gfdGaming::board::functions 

また、クライアントは、宣言と定義に分割(この場合、三目並べで)ゲーム固有のコードを持っています(TTT.h、Client.cpp)。 TTT.hは基本的に

#include "GameEngine.h" 

#define TTTtar "localhost" 
#define TTTport 2886 

using namespace gfdGaming; 
void* turnHandler(void*); 
namespace nsTicTacToe 
{ 
    GFDCON gfd; 
    const char X = 'X'; 
    const char O = 'O'; 
    string MPhostname, mySID; 
    board TTTboard; 
    bool PlayerIsX = true, isMyTurn; 
    char Player = X, Player2 = O; 

    int recon(string* datHolder = NULL, bool force = false); 
    void initMP(bool create = false, string hn = TTTtar); 
    void init(); 
    bool isTie(); 
    int turnPlayer(Index loc, char lSym = Player); 
    bool checkWin(char sym = Player); 

    int mainloop(); 

    int mainloopMP(); 

}; // NS 
私はOOPでうまく動作しないいくつかの部分があるので、それの代わりに、クラスのグループに名前空間にこれを置くことを決定しました

であり、それは、後に実装する方がはるかに簡単です。

過去にクライアントをリンクする際に問題がありましたが、この設定が機能するようです。

私のサーバーもServer.hとServer.cppの2つのファイルに分割されています。

Server.hが正確に含まれています

#include "../TicTacToe/TTT.h" // Server needs a full copy of TicTacToe code 

class TTTserv; 
struct TTTachievement_requirement { 
    Index id; 
    Index loc; 
    bool inUse; 
}; 
struct TTTachievement_t { 
    Index id; 
    bool achieved; 
    bool AND, inSameGame; 
    bool inUse; 
    bool (*lHandler)(TTTserv*); 
    char mustBeSym; 
    int mustBePlayer; 
    string name, description; 
    TTTachievement_requirement steps[safearray(8*8)]; 

}; 

class achievement_core_t : public GfdOogleTech { 
public: // May be shifted to private 
    TTTachievement_t list[safearray(8*8)]; 
public: 
    achievement_core_t(); 

    int insert(string name, string d, bool samegame, bool lAnd, int lSteps[8*8], int mbP=0, char mbS=0); 
}; 


struct TTTplayer_t { 
    Index id; 
    bool inUse; 
    string ip, sessionID; 
    char sym; 
    int desc; 
    TTTachievement_t Ding[8*8]; 
}; 
struct TTTgame_t { 
    TTTplayer_t Player[safearray(2)]; 
    TTTplayer_t Spectator; 
    achievement_core_t achievement_core; 
    Index cTurn, players; 
    port_t roomLoc; 
    bool inGame, Xused, Oused, newEvent; 
}; 


class TTTserv : public gSserver { 
    TTTgame_t Game; 
    TTTplayer_t *cPlayer; 

    port_t conPort; 
public: 
    achievement_core_t *achiev; 
    thread threads[8]; 
    int parseit(string tDat, string tsIP); 
    Index conCount; 
    int parseit(string tDat, int tlUser, TTTplayer_t** retval); 

private: 
    int parseProto(string dat, string sIP); 
    int parseProto(string dat, int lUser); 

    int cycleTurn(); 
    void setup(port_t lPort = 0, bool complete = false); 

public: 
    int newEvent; 
    TTTserv(port_t tlPort = TTTport, bool tcomplete = true); 

    TTTplayer_t* userDC(Index id, Index force = false); 
    int sendToPlayers(string dat, bool asMSG = false); 
    int mainLoop(volatile bool *play); 
}; 



// Other 
void* userHandler(void*); 
void* handleUser(void*); 

そしてCPPファイルで、私は(Server.hを含めると、メインを提供する)と、すべての機能の内容は、以前に宣言しました。

手元の問題 私のサーバーをリンクする際に問題が発生しています。具体的には、nsTicTacToeの変数ごとに重複したシンボルエラーが発生します(gfdGamingも同様です)。私は三目並べの機能を必要とするので、私は、サーバー

基本的に
ld: duplicate symbol nsTicTacToe::PlayerIsX  in Client.o and Server.o 
collect2: ld returned 1 exit status 
Command /Developer/usr/bin/g++-4.2 failed with exit code 1 

It stops once a problem is encountered, but if PlayerIsX is removed/changed temporarily than another variable causes an error 

を構築するとき、私はより良い、うまくいけば、これらのエラーを修正するために私のコードを整理する方法上の任意のアドバイスを探しています(メインは()なし)Client.cppをリンク。

免責事項: -I Iが多すぎても少なすぎても情報を提供している場合、それは私の初めて

-Iを掲示するが、これらの問題を解決するために、静的およびEXTERNを使用してみましたがあるとして、事前に謝罪、しかし、毎回.cppファイル:それはあなたが持っているものだから、明らかにそれらはあなたが重複定義に関するエラーが出る)私は

は=このすべてを読み、対応に時間がかかる誰にもありがとうござい必要なもの

+0

ヘッダーガードを使用してみてください。あなたは何も使用していません。 – DumbCoder

+1

私は以下の回答を提供しましたが、ヘッダーガードを使用しました。 – lefticus

+0

彼はトラブルを起こしているので、ヘッダーガードはおそらく彼の唯一の問題ではありませんが、それらを使用するのはいつもより良いです(私は思う?)。 – stnr

答えて

6

ではありませんTTを含むT.hの場合は、グローバルbool PlayerIsXが定義されています(nsTicTacToe名前空間ではあるが、グローバルです)。この場合、それを含むServer.cppとClient.cppです。

これを解決する1つの方法は、externを使用して定義を宣言に変更し、対応する.cppファイル(TTT.cppなど)で実際の定義を行うことです。TTT.hで

:TTT.cppで

namespace nsTicTacToe { 
    ... 
    extern bool PlayerIsX; 
    ... 
} 

#include "TTT.h" 

bool nsTicTacToe::PlayerIsX; 

など他の定義について。ところで

、適切なガード#ifdef秒を持っていることを忘れないでください:

#ifndef __TTT_H 
#define __TTT_H 
... header contents 
#endif // __TTT_H 
+0

あなたの早急な対応に感謝し、有益な情報に感謝します。それはまさに私が必要としていたことです。今は完璧に動作します。 – Gfdking

+1

@Gfdking:問題ありません。しかし、私はコード体系の改良(構造体やクラスを使用する)に関するlefticusの提案もお勧めします。 – maxelost

1

あなたは、それ自身の.cppファイルに名前空間nsTicTacToeの一部を入れて個別にコンパイルし、それをリンクすることができ ます。また、必要がある場合があります。変数のexternを宣言するだけのヘッダーファイル。それにはクライアントとサーバーの.cppファイルが含まれています。

3

あなたは、本質的に強くC++で推奨されていないグローバルを、使用していますが、それはにexternでの作業を取得できましたが、「より良い」答えはであなたのグローバルをラップするだろうC.

でなければならない場合があるされています何らかの状態オブジェクトです。

struct State 
{ 
    GFDCON gfd; 
    const char X; 
    const char O; 
    string MPhostname, mySID; 
    board TTTboard; 
    bool PlayerIsX, isMyTurn; 
    char Player, Player2; 
}; 

メインに状態オブジェクトを作成し、ゲームシステムの状態を知る必要がある各機能に渡します。

これにより、長期的にはコード編成が大幅に向上します。

+0

ありがとうございます。はい、私は、オブジェクトにデータを保持するほうが良いという振り返りで同意します。この段階で私のコードを再構成することは非常に魅力的ではありませんが、私は確かにこれを心に留めておきます=) – Gfdking

2

実際、externは必要なものです。あなたはおそらく、cppファイルにそのような変数を定義しなければならないことを認識していないかもしれません。

ヘッダー:

extern int somevar; 

ソース:

int somevar = ?; 

あなたがそれらを含めどこでもあなたがそれらのコピーを作っているヘッダにあなたのグローバルのすべてを置くことによって、あなたのコンパイラがある、まさにです約嫌だ。

+1

ありがとうございました!あなたは正しいですが、私はexternを実装する方法を少し誤解しています。今すぐ修正 – Gfdking

関連する問題