我收到链接器错误,似乎无法解决... 我在Mac OS X 10.6.8上使用Qt版本4.7和i686-apple-darwin10-g ++ - 4.2.1编译器
我似乎无法找到问题,虽然我确定这只是一个愚蠢的错误,可归因于我自己的天真......
我发布了编译器输出和涉及的2个文件(大多数)只是为了确保我不会遗漏一些重要内容。
编译器提供以下输出:
Linking CXX executable GLBall
Undefined symbols:
"BallGLWidget::resizeGL(int, int)", referenced from:
vtable for BallGLWidgetin moc_DesktopMain.cxx.o
"_main", referenced from:
start in crt1.10.6.o
"BallGLWidget::paintGL()", referenced from:
vtable for BallGLWidgetin moc_DesktopMain.cxx.o
"BallGLWidget::~BallGLWidget()", referenced from:
vtable for BallGLWidgetin moc_DesktopMain.cxx.o
"BallGLWidget::~BallGLWidget()", referenced from:
vtable for BallGLWidgetin moc_DesktopMain.cxx.o
"non-virtual thunk to BallWindow::~BallWindow()", referenced from:
vtable for BallWindowin moc_DesktopMain.cxx.o
"non-virtual thunk to BallGLWidget::~BallGLWidget()", referenced from:
vtable for BallGLWidgetin moc_DesktopMain.cxx.o
"non-virtual thunk to BallWindow::~BallWindow()", referenced from:
vtable for BallWindowin moc_DesktopMain.cxx.o
"BallWindow::~BallWindow()", referenced from:
vtable for BallWindowin moc_DesktopMain.cxx.o
"non-virtual thunk to BallGLWidget::~BallGLWidget()", referenced from:
vtable for BallGLWidgetin moc_DesktopMain.cxx.o
"BallGLWidget::initializeGL()", referenced from:
vtable for BallGLWidgetin moc_DesktopMain.cxx.o
"BallWindow::~BallWindow()", referenced from:
vtable for BallWindowin moc_DesktopMain.cxx.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
make[2]: *** [GLBall] Error 1
make[1]: *** [CMakeFiles/GLBall.dir/all] Error 2
make: *** [all] Error 2
这是DesktopMain.cpp :(注意:为简洁起见省略了标题)
//-----------------------------------------
//FILE-SCOPE POINTERS
//-----------------------------------------
static BallWindow* mainwindow;
//-----------------------------------------
//-----------------------------------------
//class BallGLWidget IMPLEMENTATIONS
//-----------------------------------------
void BallGLWidget::initializeShaders()
{
char* vs, fs;
vertexShaderHandle = glCreateShader(GL_VERTEX_SHADER);
fragmentShaderHandle = glCreateShader(GL_FRAGMENT_SHADER);
vs = readFile(VERTEX_SHADER_FILE_NAME);
fs = readFile(FRAGMENT_SHADER_FILE_NAME);
const char* vv = vs, *ff = fs;
glShaderSource(vertexShaderHandle , 1, &vv, NULL);
glShaderSource(fragmentShaderHandle, 1, &ff, NULL);
delete[] vs; delete[] fs;
glCompileShader(vertexShaderHandle);
glCompileShader(fragmentShaderHandle);
programHandle = createProgram();
glAttachShader(programHandle, vertexShaderHandle);
glAttachShader(programHandle, fragmentShaderHandle);
glLinkProgram(programHandle);
glUseProgram(programHandle);
}
void BallGLWidget::deleteShaders()
{
glDetachShader(programHandle, vertexShaderHandle);
glDetachShader(programHandle, fragmentShaderHandle);
glDeleteShader(vertexShaderHandle);
glDeleteShader(fragmentShaderHandle);
glDeleteProgram(programHandle);
}
GLuint BallGLWidget::loadTexture(const char* fptr)
{
QImage* img = new QImage();
if(!img->load(fptr))
{
//error loading image, handle error
}
//bind the texture to the current context
GLuint texHandle = bindTexture(&img);
delete img;
return texHandle;
}
void BallGLWidget::initializeGL()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
initializeShaders();
glBindAttribLocation(VERTEX_POS_NUM, VERTEX_POS_ATTRIB_NAME);
glBindAttribLocation(TEX_POS_NUM, TEX_COORD_ATTRIB_NAME);
glBindAttribLocation(COLOR_POS_NUM, COLOR_ATTRIB_NAME);
glEnableVertexArray(VERTEX_POS_NAME);
glEnableVertexArray(TEX_POS_NUM);
glEnableVertexArray(COLOR_POS_NUM);
ball_texture_handle = loadTexture(BALL_IMAGE_PATH);
samplerUniformLocation =
glGetUniformLocation(programHandle, BALL_SAMPLER_NAME);
glActiveTexture(GL_TEXTURE0 + samplerUniformLocation);
//bind it in initialization because we're only using
//1 texture in the program
glBindTexture(GL_TEXTURE_2D, ball_texture_handle);
//construct C++ objects
ball = new Ball(BALL_DIAMETER);
colorTrail = new ColorTrail(programHandle);
}
void BallGLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
ball ->draw();
colorTrail->add_segment(ball->getTopLeftCornerCoord(),
ball->getLeftCornerCoord());
ball->updatePhysics();
}
void BallGLWidget::resizeGL(int width, int height)
{
//should this be the constants or the parameters?
//where are the camera functions in OpenGL ES 2...
glViewport(0, 0, BOX_WIDTH, BOX_HEIGHT);
}
void BallGLWidget::cleanupGL()
{
deleteShaders();
}
BallGLWidget::BallGLWidget(QWidget *parent = 0)
{
}
BallGLWidget::~BallGLWidget()
{
cleanupGL();
delete ball;
delete colorTrail;
}
//-----------------------------------------
//class BallWindow IMPLEMENTATIONS
//-----------------------------------------
void BallWindow::createWindow()
{
//minimum size is defined in GlobalConstants.h
setMinimumSize(QSize(BOX_WIDTH, BOX_HEIGHT));
BallGLWidget* glWidget = new BallGLWidget;
setAttribute(Qt::WA_DeleteOnClose);
setCentralWidget(glWidget);
}
BallWindow::BallWindow(QWidget * parent = 0)
{
createWindow();
}
BallWindow::~BallWindow()
{
}
//-----------------------------------------
//main FUNCTION
//-----------------------------------------
int main(int argc, const char* argv[])
{
QApplication application(argc, argv);
mainwindow = new BallWindow();
BallWindow->show();
return application.exec();
}
DesktopMain.h:
class BallGLWidget : public QGLWidget
{
Q_OBJECT
private:
//----------------------------
//HANDLES
//----------------------------
GLuint ball_texture_handle;
GLuint vertexShaderHandle, fragmentShaderHandle;
GLuint programHandle;
GLuint samplerUniformLocation;
//----------------------------
//PRIVATE VARIABLES
//----------------------------
Ball* ball;
ColorTrail* colorTrail;
//----------------------------
//PRIVATE METHODS
//----------------------------
void initializeShaders();
void deleteShaders();
GLuint loadTexture(const char* fptr);
protected:
void initializeGL();
void paintGL();
void resizeGL(int width, int height);
void cleanupGL();
public:
BallGLWidget(QWidget *parent = 0);
virtual ~BallGLWidget();
};
class BallWindow : public QMainWindow
{
Q_OBJECT
private:
void createWindow();
public:
BallWindow(QWidget *parent = 0);
~BallWindow();
};
//void onProgramExit();
int main(int argc, const char* argv[]);
编辑:我正在使用CMake进行此项目。很抱歉忘记在原始问题中发布此内容!
这是CMakeLists.txt:
cmake_minimum_required(VERSION 2.6)
project(GLBall)
SET(ENV{SOURCES} src/Ball.cpp src/Ball.h src/ColorTrail.cpp src/ColorTrail.h src/DesktopMain.h src/DesktopMain.cpp src/GlobalConstants.h src/ShaderOps.h)
FIND_PACKAGE(Qt4 REQUIRED)
FIND_PACKAGE(OpenGL REQUIRED)
SET(QT_USE_QTOPENGL TRUE)
QT4_WRAP_CPP(HEADERS_MOC src/DesktopMain.h)
INCLUDE(${QT_USE_FILE})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
ADD_DEFINITIONS(${QT_DEFINITIONS})
SET(CMAKE_EXE_COMPILER_FLAGS -g -v)
ADD_EXECUTABLE(GLBall ${SOURCES} ${HEADERS_MOC})
TARGET_LINK_LIBRARIES(GLBall ${QT_LIBRARIES})
答案 0 :(得分:2)
就像Luca说的那样,确保你正常运行qmake,这是通常的步骤 -
$ qmake -project
$ qmake
$ make
($是shell提示符)
如果这不能解决问题,也许您应该告诉我们您的目录结构。
答案 1 :(得分:2)
我相信
SET(ENV{SOURCES} src/Ball.cpp src/Ball.h src/ColorTrail.cpp src/ColorTrail.h src/DesktopMain.h src/DesktopMain.cpp src/GlobalConstants.h src/ShaderOps.h)
应该是
SET(SOURCES src/Ball.cpp src/Ball.h src/ColorTrail.cpp src/ColorTrail.h src/DesktopMain.h src/DesktopMain.cpp src/GlobalConstants.h src/ShaderOps.h)
因为您之后引用${SOURCES}
,而不是环境变量。那当然可以做到。实际上,“来源”不应该包含标题(将Q_OBJECT宏的头文件传递给qt4_wrap_cpp
,就像你正在做的那样)。这是修改后的文件:
cmake_minimum_required(VERSION 2.6)
project(GLBall)
set(SOURCES src/Ball.cpp src/ColorTrail.cpp src/DesktopMain.cpp)
find_package(Qt4 REQUIRED)
find_package(OpenGL REQUIRED)
set(QT_USE_QTOPENGL TRUE)
include(${QT_USE_FILE})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_definitions(${QT_DEFINITIONS})
set(CMAKE_EXE_COMPILER_FLAGS -g -v)
qt4_wrap_cpp(HEADERS_MOC src/DesktopMain.h)
add_executable(GLBall ${SOURCES} ${HEADERS_MOC})
target_link_libraries(GLBall ${QT_LIBRARIES})
此外,您可以在运行CMAKE_BUILD_TYPE
或ccmake
时将cmake-gui
更改为“调试”(或“发布”),而不是手动设置编译器标志。
可能与此无关,但为了以防万一,我通常会在qt4_wrap_cpp
之后发出include(${QT_USE_FILE})
次来电。
答案 2 :(得分:1)
尝试清理项目运行qmake。然后重建。