g++ mysterious linker error

Started by
4 comments, last by SecondAttempt2 15 years, 6 months ago
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);
		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);
		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.
Advertisement
Could you repost that code using source tags?

  // Like this
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.
@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.hstruct Foo{    void frobnicate()    {        // implementation inline here        // ...    }};

Or:
// foo.hstruct 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.
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
Thanks! Problem solved.

This topic is closed to new replies.

Advertisement