3

I know this has been asked probably a thousand times, but I've been biting my nails on this one for a few days now. I'm fairly new to C++ and this is my first time using Visual Studio.

I'm trying to modify the TORCS Racing Simulator for a competition at my University. Most of this has already been done, so only parts of what I'm posting is actually my code. But I added some new functions to it and I'm having trouble with them.

The whole thing worked fine in Linux with g++ but when I try to compile it in Visual Studio 2005, I get an Unresolved external symbol error.

I added a new project to the Solution, which uses functions from other projects.

In this new project I call the function:

getisDerbyDuel()

which is declared in raceinit.h, which I included in the new project.

#ifndef _RACEINIT_H_
#define _RACEINIT_H_

#define RACE_ENG_CFG    "config/raceengine.xml"

extern void ReInit(void);
extern void ReShutdown(void);
extern void ReStartNewRace(void * /* dummy */);
extern void ReAddRacemanListButton(void *menuHandle);
extern int  ReInitCars(void);
extern int  ReInitTrack(void);
extern void ReRaceCleanup(void);
extern void ReRaceCleanDrivers(void);
extern char *ReGetCurrentRaceName(void);
extern char *ReGetPrevRaceName(void);
extern bool getisDerbyDuel(void);
extern void setisDerbyDuel(bool isDerbyDuel);

extern tModList *ReRaceModList;

#endif /* _RACEINIT_H_ */

and defined in raceinit.cpp:

 bool _isDerbyDuel = true;

void setisDerbyDuel(bool isDerbyDuel) {
    _isDerbyDuel = isDerbyDuel;
}
bool getisDerbyDuel(void) {
    return _isDerbyDuel;
}

The raceinit.h and raceinit.cpp are in a different projects in my Solution called client, which compiles without errors. I also added the client.lib to the dependencies in my project.

When compiling I get the following output:

1>Generating Code... 
1>Compiling resources...
1>Linking...
1>   Creating library .\Release/championship2010server.lib and object      .\Release/championship2010server.exp
1>championship2010server.obj : error LNK2019: unresolved external symbol "bool __cdecl     getisDerbyDuel(void)" (?getisDerbyDuel@@YA_NXZ) referenced in function "void     __cdecl drive(int,struct CarElt *,struct Situation *)"     (?drive@@YAXHPAUCarElt@@PAUSituation@@@Z)
1>.\Release/championship2010server.dll : fatal error LNK1120: 1 unresolved externals
1>Build log was saved at "file://c:\Users\Administrator\Desktop\torcs-verylasttry    \src\drivers\championship2012server\Release\BuildLog.htm"
1>championship2010server - 2 error(s), 9 warning(s)
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========    

Any ideas are appreciated, I don't know what to try anymore.


EDIT:

Thanks for your answers. I tried changing the external thing, so the flag itself is declared external in the header file and the getter is not (and several combinations) but nothing seems to change the error output.

I'm not exactly sure what is meant by exporting the functions. A quick Google search lead me to this:

[..]
extern void ReRaceCleanDrivers(void);
extern char *ReGetCurrentRaceName(void);
extern char *ReGetPrevRaceName(void);
#ifdef __cplusplus
extern "C" {  // only need to export C interface if
              // used by C++ source code
#endif
extern bool __declspec( dllimport ) getisDerbyDuel(void);
extern void __declspec( dllimport ) setisDerbyDuel(bool isDerbyDuel);

#ifdef __cplusplus
}
#endif
extern bool _isDerbyDuel;
[...]

and

extern "C" {
#include <raceinit.h>
}

Which changed the error Output to this:

1>championship2010server.obj : error LNK2019: unresolved external symbol     __imp__getisDerbyDuel referenced in function "void __cdecl drive(int,struct CarElt *,struct     Situation *)" (?drive@@YAXHPAUCarElt@@PAUSituation@@@Z)
1>.\Release/championship2010server.dll : fatal error LNK1120: 1 unresolved externals

I just don't know whats wrong here.


EDIT TWO:

So, after reading up on importing/exporting functions I adjusted my code.
The header file, where the unresolved function is declared now looks like this:

#ifdef __cplusplus
extern "C" {  // only need to export C interface if
              // used by C++ source code
#endif
 __declspec( dllexport ) bool getisDerbyDuel(void);
 __declspec( dllexport ) void setisDerbyDuel(bool isDerbyDuel);

#ifdef __cplusplus
}
#endif
extern bool _isDerbyDuel;

The file where I call the function doesn't have a header file, but I tried to declare the imported function according to the other functions in the file:

[...]
static tTrack *curTrack;
static int RESTARTING[NBBOTS];

static void initTrack(int index, tTrack* track, void *carHandle,
        void **carParmHandle, tSituation *s);
static void newrace(int index, tCarElt* car, tSituation *s);
extern "C" void drive(int index, tCarElt* car, tSituation *s);
static void endrace(int index, tCarElt *car, tSituation *s);
static void shutdown(int index);
static int InitFuncPt(int index, void *pt);

__declspec( dllimport ) bool getisDerbyDuel(void);
[...]

The header is included just like any other and the function is called like this:

if (getisDerbyDuel()) {
[...]

The error output now changed to this:

error LNK2019: unresolved external symbol _getisDerbyDuel referenced in function _drive

So it seems to me that if I just solved some C/C++ compatibility issue (or made it worse, I'm not even sure anymore) but the linker problem remains unchanged.

Any Ideas? I'm kinda put off now, but I need to get this to work, or my Boss is going to be pissed :)

john_science
  • 6,325
  • 6
  • 43
  • 60
Dennis Schwartz
  • 101
  • 1
  • 1
  • 7
  • Have you exported your new functions? In Linux, functions and classes are exported by default and in Windows they're not. This would explain why the linker is complaining under Windows and not Linux – SirGuy Apr 02 '12 at 16:55
  • It is saying that getisDerbyDuel() has external linkage. In C, external linkage is default. –  Apr 02 '12 at 16:57
  • http://stackoverflow.com/questions/496448/how-to-correctly-use-the-extern-keyword-in-c –  Apr 02 '12 at 17:00
  • Thanks for your answers, i edited my post after trying your suggestions. – Dennis Schwartz Apr 02 '12 at 17:57
  • Does your solution include `raceinit.cpp`, ie. is it compiled along with the rest of the resources? – Michael Foukarakis Apr 02 '12 at 18:00
  • yes. It's compiled. I also deleted the client.lib and client.dll (which contain raceinit.cpp) manually and rebuild them. Didn't change anything either. – Dennis Schwartz Apr 03 '12 at 09:20

2 Answers2

7

As i said, I'm new to Visual Studio but this is still a little embarassing. I found my error and it actually wasn't in my code.
In addition to the linker input etc. i had to add the project containing raceinit.cpp to the references in my new project. That solved my problem.

Dennis Schwartz
  • 101
  • 1
  • 1
  • 7
3

Visual studio uses a different method for path includes and lib linking.

Check your project settings:

  1. right click your project and select 'settings'
  2. under 'Configuration properties' check under 'C/C++' that you have added the paths to the headers you need
  3. Now check under 'Linker' that you have added the path to your lib file under 'Additional Library Directories'
  4. Also check you have added the lib under 'Linker>Input>Additional Dependencies'

Hope the above helps.

EdChum
  • 376,765
  • 198
  • 813
  • 562
  • Thank you for your answer. But i did all of that and double checked several times already. If i copy the raceinit.h and raceinit.cpp from their original directory into the directory of my new project i get different errors, but i don't think that's a very good approach anyway. – Dennis Schwartz Apr 02 '12 at 17:35