• Advertisement
Sign in to follow this  

VC++ externs (hang on, almost done debugging)

This topic is 4179 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have one more question, when the program started to link It gave me an error for every .cpp that has an extern. For example, files that got an extern to the Camera class like this: extern CCamera Camera; got errors like this: Linking... CController.obj : error LNK2019: unresolved external symbol "class CCamera Camera" (?Camera@@3VCCamera@@A) referenced in function "public: void __thiscall CController::SaveNet(void)" (?SaveNet@CController@@QAEXXZ) CGun.obj : error LNK2001: unresolved external symbol "class CCamera Camera" (?Camera@@3VCCamera@@A) CVehicle.obj : error LNK2001: unresolved external symbol "class CCamera Camera" (?Camera@@3VCCamera@@A) ParticleEngine.obj : error LNK2001: unresolved external symbol "class CCamera Camera" (?Camera@@3VCCamera@@A) Terrain.obj : error LNK2001: unresolved external symbol "class CCamera Camera" (?Camera@@3VCCamera@@A) BSP.obj : error LNK2001: unresolved external symbol "class CCamera Camera" (?Camera@@3VCCamera@@A) Building.obj : error LNK2001: unresolved external symbol "class CCamera Camera" (?Camera@@3VCCamera@@A) Whats the problem with using externs in VC++. (I know that in general it's not good practice but for some classes like this camera class that I needed to put in all the files that render stuff it was much easier:)) Thanks.

Share this post


Link to post
Share on other sites
Advertisement
Well, the variable has to be defined somewhere.

i.e. there ought to be a cpp file with CCamera Camera; without the extern.

With extern, you promised that you would define the variable, placating the compiler. You'd better make good on your promise, otherwise don't be surprised that the linker complains.

Share this post


Link to post
Share on other sites
yeah your're right, now I noticed that I forgot to include a cpp were some externs were defined. But now there's another linker problem, in every cpp that I use gl commands I get linker errors like:

Terrain.obj : error LNK2001: unresolved external symbol __imp__glColor3f@12
game.obj : error LNK2001: unresolved external symbol __imp__glColor3f@12
CMenu.obj : error LNK2001: unresolved external symbol __imp__glColor3f@12
CVehicle.obj : error LNK2001: unresolved external symbol __imp__glColor3f@12
Selection.obj : error LNK2001: unresolved external symbol __imp__glColor3f@12
Steering.obj : error LNK2001: unresolved external symbol __imp__glColor3f@12
BSP.obj : error LNK2019: unresolved external symbol __imp__glColor3f@12 referenced in function "private: void __thiscall CBspTree::Render(struct BSP *)" (?Render@CBspTree@@AAEXPAUBSP@@@Z)
Building.obj : error LNK2001: unresolved external symbol __imp__glColor3f@12
CController.obj : error LNK2001: unresolved external symbol __imp__glColor3f@12
CGun.obj : error LNK2001: unresolved external symbol __imp__glColor3f@12

What does this mean?
Thanks.

Share this post


Link to post
Share on other sites
Similar problem, similar cause: the linker needs to get the glColor3f function somewhere, such as in a library that you tell it to link to... [wink]


Unresolved external symbol = you told me XYZ exists so I've let you use it, but now I can't find it anywhere.

Share this post


Link to post
Share on other sites
Thanks, I linked the lib's and those errors went away. I still have some simaler error regarding a class called CFrustum. I declared CFrustum Frustum; in a cpp and then in the other files like BSP.cpp I did:
extern CFrustum Frustum. But now I'm getting errors like:

Linking...
BSP.obj : error LNK2019: unresolved external symbol "public: bool __thiscall CFrustum::BoxInFrustum(float,float,float,float,float,float)" (?BoxInFrustum@CFrustum@@QAE_NMMMMMM@Z) referenced in function "private: void __thiscall CBspTree::Render(struct BSP *)" (?Render@CBspTree@@AAEXPAUBSP@@@Z)
BSP.obj : error LNK2019: unresolved external symbol "public: bool __thiscall CFrustum::SphereInFrustum(float,float,float,float)" (?SphereInFrustum@CFrustum@@QAE_NMMMM@Z) referenced in function "private: void __thiscall CBspTree::RenderTrees(struct BSP *)" (?RenderTrees@CBspTree@@AAEXPAUBSP@@@Z)
game.obj : error LNK2001: unresolved external symbol "public: bool __thiscall CFrustum::SphereInFrustum(float,float,float,float)" (?SphereInFrustum@CFrustum@@QAE_NMMMM@Z)
BSP.obj : error LNK2019: unresolved external symbol "public: void __thiscall CFrustum::CalculateFrustum(void)" (?CalculateFrustum@CFrustum@@QAEXXZ) referenced in function "public: void __thiscall CBspTree::RenderMap(void)" (?RenderMap@CBspTree@@QAEXXZ)

Frustum.h:

#ifndef FRUSTRUM_H
#define FRUSTRUM_H

#include <windows.h>
#include <math.h>
#include <gl\gl.h> // Header File For The OpenGL32 Library
#include <gl\glu.h>
// This will allow us to create an object to keep track of our frustum
class CFrustum {

public:
// Call this every time the camera moves to update the frustum
void CalculateFrustum();

// This takes a 3D point and returns TRUE if it's inside of the frustum
bool PointInFrustum(float x, float y, float z);

// This takes a 3D point and a radius and returns TRUE if the sphere is inside of the frustum
bool SphereInFrustum(float x, float y, float z, float radius);

// This takes the center and half the length of the cube.
bool BoxInFrustum( float x, float y, float z, float height, float width, float depth );

private:

// This holds the A B C and D values for each side of our frustum.
float m_Frustum[6][4];
};

#endif




BSP.cpp:

#include "BSP.h"
#include "Frustum.h"

extern CFrustum Frustum;
extern bool multitextureSupported;


...

void CBspTree :: Render(BSP* node)
{
if(node->is_leaf)
{
glColor3f(1,1,1);

if((node->centerX == PickedCenter.x)&&(node->centerZ == PickedCenter.z))
{
num_picked++;
PickedCenter.y = node->distance;
}

if(Frustum.BoxInFrustum( SCALE_SIDE*node->centerX, node->centerY,
SCALE_SIDE*node->centerZ, node->height/2, (SCALE_SIDE*node->width)/2,
(SCALE_SIDE*node->depth)/2))
{

RenderHeightMap(p_HeightMap, (int)(node->centerX - node->width/2),
(int)(node->centerZ - node->depth/2),
(int)(node->centerX + node->width/2), (int)(node->centerZ + node->depth/2) );
number_of_parts++;
}
}
else
{
if(Frustum.BoxInFrustum( SCALE_SIDE*node->p_sec1->centerX, node->p_sec1-
>centerY, SCALE_SIDE*node->p_sec1->centerZ, node->p_sec1->height/2,
(SCALE_SIDE*node->p_sec1->width)/2, (SCALE_SIDE*node->p_sec1->depth)/2))
Render(node->p_sec1);

if(Frustum.BoxInFrustum( SCALE_SIDE*node->p_sec2->centerX, node->p_sec2-
>centerY, SCALE_SIDE*node->p_sec2->centerZ, node->p_sec2->height/2,
(SCALE_SIDE*node->p_sec2->width)/2, (SCALE_SIDE*node->p_sec2->depth)/2))
Render(node->p_sec2);

if(Frustum.BoxInFrustum( SCALE_SIDE*node->p_sec3->centerX, node->p_sec3-
>centerY, SCALE_SIDE*node->p_sec3->centerZ, node->p_sec3->height/2,
(SCALE_SIDE*node->p_sec3->width)/2, (SCALE_SIDE*node->p_sec3->depth)/2))
Render(node->p_sec3);
if(Frustum.BoxInFrustum( SCALE_SIDE*node->p_sec4->centerX, node->p_sec4-
>centerY, SCALE_SIDE*node->p_sec4->centerZ, node->p_sec4->height/2,
(SCALE_SIDE*node->p_sec4->width)/2, (SCALE_SIDE*node->p_sec4->depth)/2))
Render(node->p_sec4);
}
}



For some reason it has a problem with the Frustum functions. and also, even in game.cpp were the CFrustum Frustum is defined, when I use Frustum::SphereInFrustum(float,float,float,float) , it gives a linker error.
Whats the problem with this?
Thanks a lot! I hope to get this working today!

Share this post


Link to post
Share on other sites
Quote:
Original post by daniel_i_l
include a cpp


You shouldn't include .cpp files. You just don't do that and you definately don't need to. Only include .h files.

Since I don't see any .cpp including in your source file, prehaps you just miss-typed or -thought?

Share this post


Link to post
Share on other sites
I take it you also have a Frustrum.cpp that implements these functions. Are you sure this is being compiled and its object file linked into your project correctly?

By the way, it is probably not good practice to manually put extern CWhatever Whatever in a cpp file that uses the object. If you change the name of the object or its type and forget to update one of these lines somewhere, the compile-stage will possibly still work but you end up with a hard to track down link error.

Normal practice is to put the extern in a header file that is included by any units that use it like:

objects.h

#include "frustrum.h"

extern CFrustrum Frustrum;





objects.cpp

#include "objects.h"

CFrustrum Frustrum(params);





main.cpp

#include "objects.h"

int main()
{
Frustrum.ExecuteMyMMORPG(); // etc
}





This way you centralise the declaration and the extern into one place each so that if anything changes, you only have to update it in one place.

With the other approach, if you were to now change the name of Frustrum to MyFrustrum but forgot to change one of your extern CFrustrum Frustrum lines somewhere, the compile stage would still work, because it would just be told "There will be a CFrustrum object called Frustrum defined elsewhere before we link" but the linker will then bomb out because it can't find it, making it harder to track the error down.

With the approach I have described, if you changed the name of the object but forgot to update the use of that name somewhere, it would be caught by the compiler with line numbers and so on displayed, making it a lot easier to correct.

HTH Paul

Share this post


Link to post
Share on other sites
Thanks for that, I fixed it and it compiled!

But then when the program got to were I load trees from a bitmap using glaux I got an error in the end, here's the function:

AUX_RGBImageRec *LoadBMP(char *Filename)
{
FILE *File=NULL;

if (!Filename)
{
return NULL;
}

File=fopen(Filename,"r");

if (File)
{
fclose(File);
return auxDIBImageLoad(Filename);
}

return NULL;
}
//------------------------LoadGLMap---------------------------
//
// This loads the trees, buldings, fences.... used by the
// graphics files
//
//------------------------------------------------------------
int LoadGLMap()
{
int Status=FALSE,i,j;
GLuint texID = 10;
unsigned char *p;
int R,G,B;
double x,y,z;
bool reflect = false;
bool justonce = true;
AUX_RGBImageRec *TextureImage[1];

memset(TextureImage,0,sizeof(void *)*1);
if (TextureImage[texID]=LoadBMP("textures/treemap.bmp"))
{
Status=TRUE;
p = TextureImage[texID]->data;
//go through the data
for(j=511;j>=-1;j-=1)
{
for(i=0;i<512;i+=1)
{
R = *p; p+=1;
G = *p; p+=1;
B = *p; p++;

// ...
// analyze R,G,B
// ...

}//fori
}//forj
} //if tex

if (TextureImage[texID])
{
=> if (TextureImage[texID]->data)
{
free(TextureImage[texID]->data);
}

free(TextureImage[texID]);
}

return Status;
}



the error is near the end were the arrow (=>) is. It said:
sizeX = CXX0030: Error: expression cannot be evaluated
sizeY = CXX0030: Error: expression cannot be evaluated
data = CXX0030: Error: expression cannot be evaluated

Why not? Whats the problem? (this is the last bug cause when I disabled loading the trees it ran fine!
Thanks.

[Edited by - daniel_i_l on August 13, 2006 4:21:35 AM]

Share this post


Link to post
Share on other sites
I don't understand your code. You are going:

GLuint texID = 10;

AUX_RGBImageRec *TextureImage[1];

Then you are trying to access TextureImage[texID]. This doesn't explain why the last line won't compile, but since as far as I can see you only want one pointer to a TextureImage, why can't you get rid of the texID, declare:

AUX_RGBImageRec *TextureImage=LoadBMP("whatever.bmp");

then just use TextureImage->data etc directly? What you are doing is declaring an array of such pointers, but with only one item in the array, then you are trying to access the tenth item in the array.

If it had compiled, it would have crashed when it ran as far as I can see.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement