Sign in to follow this  
SecondAttempt2

g++ mysterious linker error

Recommended Posts

SecondAttempt2    122
Hi. Could somebody help me with this problem? I am trying to make OpengL/SDL wrapper library. The library and test program compile fine, but linking gives an undefined reference wherever I use struct Pattern in the test program. I am completely mystified because struct Pattern should work and is used in the library. Does anybody have any ideas? NewProject.cpp
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#include <stack>
#include <iostream>
using namespace std;
//Globals:
SDL_Surface* screen;
struct Vector{
	float x,y,z;
	Vector(){
		x=0.0f;
		y=0.0f;
		z=0.0f;
	}
	Vector(float x2,float y2,float z2){
		x=x2;
		y=y2;
		z=z2;
	}
	Vector operator+(Vector v2){
		Vector tmp;
		tmp.x=x+v2.x;
		tmp.y=y+v2.y;
		tmp.z=z+v2.z;
		return tmp;
	}
	Vector operator-(Vector v2){
		Vector tmp;
		tmp.x=x-v2.x;
		tmp.y=y-v2.y;
		tmp.z=z-v2.z;
		return tmp;
	}
	Vector operator*(Vector v2){
		Vector tmp;
		tmp.x=x*v2.x;
		tmp.y=y*v2.y;
		tmp.z=z*v2.z;
		return tmp;
	}
	Vector operator/(Vector v2){
		Vector tmp;
		tmp.x=x/v2.x;
		tmp.y=y/v2.y;
		tmp.z=z/v2.z;
		return tmp;
	}
	void operator+=(Vector v2){
		x+=v2.x;
		y+=v2.y;
		z+=v2.z;
	}
	void operator=(Vector v2){
		x=v2.x;
		y=v2.y;
		z=v2.z;
	}
	Vector operator+(float v2){
		Vector tmp;
		tmp.x=x+v2;
		tmp.y=y+v2;
		tmp.z=z+v2;
		return tmp;
	}
	Vector operator-(float v2){
		Vector tmp;
		tmp.x=x-v2;
		tmp.y=y-v2;
		tmp.z=z-v2;
		return tmp;
	}
	Vector operator*(float v2){
		Vector tmp;
		tmp.x=x*v2;
		tmp.y=y*v2;
		tmp.z=z*v2;
		return tmp;
	}
	Vector operator/(float v2){
		Vector tmp;
		tmp.x=x/v2;
		tmp.y=y/v2;
		tmp.z=z/v2;
		return tmp;
	}
	void operator+=(float v2){
		x+=v2;
		y+=v2;
		z+=v2;
	}
	void operator=(float v2){
		x=v2;
		y=v2;
		z=v2;
	}
};
Vector mVector(float x,float y,float z){
	Vector tmp(x,y,z);
	return tmp;
}
struct Pattern{
	stack<Vector> col;
	int length,procedure;
	Pattern(){
		length=0;
		procedure=0;
	}
	Pattern(Vector c){
		col.push(c);
		length=1;
	}
	Pattern(Vector list[],int len,int proc){
		for(int i=0;i<len;i++)col.push(list[i]);
		length=len;
		procedure=proc;
	}
	void Push(Vector vector){
		col.push(vector);
		length+=1;
	}
	void Pop(){
		col.pop();
		length-=1;
	}
	Vector Top(){
		Vector tmp;
		tmp=col.top();
		return tmp;
	}
	void Procedure(int proc){
		procedure=proc;
	}
};
struct Polygon{
	stack<Vector> draw;
	int length,type;
	Polygon(){
		length=0;
		type=0;
	}
	Polygon(Vector a){
		draw.push(a);
		length=1;
		type=1;
	}
	Polygon(Vector a,Vector b){
		draw.push(a);
		draw.push(b);
		length=2;
		type=2;
	}
	Polygon(Vector a,Vector b,Vector c){
		draw.push(a);
		draw.push(b);
		draw.push(c);
		length=3;
		type=3;
	}
	Polygon(Vector a,Vector b,Vector c,Vector d){
		draw.push(a);
		draw.push(b);
		draw.push(c);
		draw.push(d);
		length=4;
		type=4;
	}
	Polygon(Vector list[],int length2,int type2){
		for(int i=0;i<length;i++)draw.push(list[i]);
		length=length2;
		type=type2;
	}
	void Push(Vector vector){
		draw.push(vector);
		length+=1;
	}
	void Pop(){
		draw.pop();
		length-=1;
	}
	void Type(int tp){
		type=tp;
	}
	Vector Top(){
		Vector tmp;
		tmp=draw.top();
		return tmp;
	}
};
Polygon mPolygon(Vector a){
	Polygon tmp(a);
	return tmp;
}
Polygon mPolygon(Vector a,Vector b){
	Polygon tmp(a,b);
	return tmp;
}
Polygon mPolygon(Vector a,Vector b,Vector c){
	Polygon tmp(a,b,c);
	return tmp;
}
Polygon mPolygon(Vector a,Vector b,Vector c,Vector d){
	Polygon tmp(a,b,c,d);
	return tmp;
}
Polygon mPolygon(Vector list[],int length,int type){
	Polygon tmp(list,length,type);
	return tmp;
}
void Init(int x,int y){
	float ratio;
	SDL_Init(SDL_INIT_EVERYTHING);
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,16);
	SDL_GL_SetAttribute(SDL_GL_RED_SIZE,8);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,8);
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8);
	SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,8);
	screen=SDL_SetVideoMode(x,y,0,SDL_OPENGL|SDL_HWPALETTE|	SDL_GL_DOUBLEBUFFER|SDL_HWSURFACE|SDL_HWACCEL);
	glShadeModel(GL_SMOOTH);
	glClearColor(0.0f,0.0f,0.0f,0.0f);
	glClearDepth(1.0f);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
	if(y==0)y=1;
	ratio=(float)x/(float)y;
	glViewport(0,0,(GLsizei)x,(GLsizei)y);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f,ratio,0.1f,600.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}
void Quit(){
	SDL_Quit();
}
void Delay(int time){
	SDL_Delay(time);
}
void Clear(){
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
}
void Reset(){
	glLoadIdentity();
}
void Translate(Vector vector){
	glTranslatef(vector.x,vector.y,vector.z);
}
void Rotate(Vector vector,float val){
	glRotatef(val,vector.x,vector.y,vector.z);
}
void Flip(){
	SDL_GL_SwapBuffers();
}
void Draw(Polygon poly,Pattern col){
	stack<Vector> apoly,acol;
	int j=0;
	switch(poly.type){
		case 1:
			glBegin(GL_POINTS);
		break;
		case 2:
			glBegin(GL_LINES);
		break;
		case 3:
			glBegin(GL_TRIANGLES);
		break;
		case 4:
			glBegin(GL_QUADS);
		break;
	}
	switch(col.procedure){
		case 1:
		for(int i=0;i<poly.length;i++){
			acol.push(col.col.top());
			glColor3f(acol.top().x,acol.top().y,acol.top().z);
			if(!j>=col.length){
				col.col.pop();
				j++;
			}
			if(poly.draw.empty()){
				apoly.push(poly.draw.top());
				glVertex3f(apoly.top().x,apoly.top().y,apoly.top().z);
				poly.draw.pop();
			}
		};
		break;
	}
	glEnd();
	while(!apoly.empty()){
		poly.draw.push(apoly.top());
		apoly.pop();
	}
	while(!acol.empty()){
		col.col.push(acol.top());
		acol.pop();
	}
}
NewProject.h
#pragma once
#include "Core2.h"
using namespace std;
//SDL:
void Init(int x,int y);
void Quit();
void Delay(int time);
//OpenGL:
void Clear();
void Reset();
void Translate(Vector vector);
void Rotate(Vector vector,float val);
void Flip();
void Draw(Polygon poly,Pattern col);
Core2.h
#pragma once
#include <stack>
using namespace std;
struct Vector{
	float x,y,z;
	Vector();
	Vector(float x,float y2,float z2);
	Vector operator+(Vector v2);
	Vector operator-(Vector v2);
	Vector operator*(Vector v2);
	Vector operator/(Vector v2);
	void operator+=(Vector v2);
	void operator=(Vector v2);
	Vector operator+(float v2);
	Vector operator-(float v2);
	Vector operator*(float v2);
	Vector operator/(float v2);
	void operator+=(float v2);
	void operator=(float v2);
};
Vector mVector(float x,float y,float z);
struct Polygon{
	stack<Vector> draw;
	int length,type;
	Polygon();
	Polygon(Vector a);
	Polygon(Vector a,Vector b);
	Polygon(Vector a,Vector b,Vector c);
	Polygon(Vector a,Vector b,Vector c,Vector d);
	Polygon(Vector list[],int length2,int type2);
	void Push(Vector vector);
	void Pop();
	void Type(int tp);
	Vector Top();
};
Polygon mPolygon(Vector a);
Polygon mPolygon(Vector a,Vector b);
Polygon mPolygon(Vector a,Vector b,Vector c);
Polygon mPolygon(Vector a,Vector b,Vector c,Vector d);
Polygon mPolygon(Vector list[],int length,int type);
struct Pattern{
	stack<Vector> col;
	int length,procedure;
	Pattern();
	Pattern(Vector c);
	Pattern(Vector list[],int len,int proc);
	void Push(Vector vector);
	void Pop();
	Vector Top();
	void Procedure(int proc);
};
Test.cpp
#include "NewProject.h"

int main(){
	Polygon poly(mVector(-1.0f,-1.0f,0.0f),mVector(1.0f,-1.0f,0.0f),mVector(1.0f,1.0f,0.0f),mVector(-1.0f,1.0f,0.0f));
	Pattern col;
	col.Procedure(1);
	col.Push(mVector(1.0f,0.0f,1.0f));
	col.Push(mVector(0.0f,0.0f,1.0f));
	col.Push(mVector(0.0f,1.0f,0.0f));
	col.Push(mVector(1.0f,0.0f,0.0f));
	Init(500,500);
	Clear();
	Reset();
	Translate(mVector(0.0f,0.0f,-5.0f));
	Draw(poly,col);
	Flip();
	Delay(5000);
	Quit();
	return 0;
}
The error: scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... g++ -o NewProject.o -c NewProject.cpp g++ -o Test.o -c Test.cpp Test.cpp:21:2: warning: no newline at end of file ar rc libNewProject.a NewProject.o ranlib libNewProject.a g++ -o Test Test.o -L. -L/usr/lib -lNewProject -lGL -lGLU -lSDL Test.o: In function `main': Test.cpp:(.text+0x125): undefined reference to `Pattern::Pattern()' Test.cpp:(.text+0x13b): undefined reference to `Pattern::Procedure(int)' Test.cpp:(.text+0x187): undefined reference to `Pattern::Push(Vector)' Test.cpp:(.text+0x1d3): undefined reference to `Pattern::Push(Vector)' Test.cpp:(.text+0x21f): undefined reference to `Pattern::Push(Vector)' Test.cpp:(.text+0x26b): undefined reference to `Pattern::Push(Vector)' collect2: ld returned 1 exit status scons: *** [Test] Error 1 scons: building terminated because of errors.

Share this post


Link to post
Share on other sites
SiCrane    11839
When you're linking your project you only use the Test.o file not the NewProject.o. You'll want to use both at the same time.

Share this post


Link to post
Share on other sites
rip-off    10976
@SiCrane
He appears to be making a static library from NewProject.o, and is including that in the build. So, all else being correct, I can't see why it wouldn't work.

@SecondAttempt2
I believe the problem is related to how you are defining your structures and member functions. Either implement the member functions inline in the header, or regularly (non-inline) in the source file.

E.g:

// foo.h

struct Foo
{
void frobnicate()
{
// implementation inline here
// ...
}
};



Or:

// foo.h

struct Foo
{
// simply declare the function, don't define it yet.
void frobnicate();
};

// foo.cpp

#include "foo.h"

void Foo::frobnicate()
{
// Regular implementation here
// ...
}




I suspect the compiler isn't generating any code for the functions defined inside the structure bodies in the source file, hence the linker errors.

I would strongly recommend against duplicating the structures themselves - that is bad idea. It will require more maintenance in the long run.

Share this post


Link to post
Share on other sites
Mattijs2    122
If NewProject.cpp #included NewProject.h, you would get an error, since Vector is defined in both Core2.h and NewProject.cpp.
So there are 2 Vectors defined. One without implementations and one with implementations

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this