C ++中的多个定义

时间:2013-06-24 19:07:01

标签: c++ qt opengl

在名为gl_ext.h的文件中,我有以下内容:

#ifndef GLEXT_H_INCLUDED
#define GLEXT_H_INCLUDED

#include <stdexcept>

#ifdef WIN32
#include <Windows.h>
#include <GL/GL.h>
#include <GL/glext.h>
# define glGetProcAddress(arg) wglGetProcAddress(arg)
#elif __linux__
#include <GL/gl.h>
#include <GL/glext.h>
# include <GL/glx.h>
# define glGetProcAddress(arg) glXGetProcAddress((const GLubyte*)arg)
#endif

PFNGLCREATESHADERPROC glCreateShader = 0;

namespace glext
{
  bool load_gl_extensions()
  {
    static bool loaded = false;
    if (loaded) {
      return true;
    }
    if (!glCreateShader) {
      glCreateShader = 
        (PFNGLCREATESHADERPROC)(glGetProcAddress("glCreateShader"));
      if (!glCreateShader) {
        throw "Failed to load glCreateShader";
      }
    }
  }
}
#endif

使用以下.pro文件在qt creator中构建时

QT += core gui opengl

TEMPLATE = app
TARGET = GLExtensions
INCLUDEPATH += .

LIBS += -lGL
HEADERS += gl_ext.h \
           qtrenderer.h        

SOURCES += main.cpp \
           qtrenderer.cpp

此“标题库”的用法如下: main.cpp中

#include <QtGui/QApplication>
#include "qtrenderer.h"

int main(int argc, char * argv[]) {
  QApplication app(argc, argv);

  QtRenderer *renderer = new QtRenderer();
  renderer->show();

  app.exec();
}

qtrenderer.h

#ifndef QTRENDERER_H_INCLUDED
#define QTRENDERER_H_INCLUDED

#include <QtCore/QObject>
#include <QtOpenGL/QGLWidget>

#include <gl_ext.h>

class QtRenderer : public QGLWidget
{

  Q_OBJECT

private:
  QtRenderer(const QtRenderer &other);
  QtRenderer &operator = (const QtRenderer &other);

protected:
  virtual void paintGL();
  virtual void initializeGL();

public:
  QtRenderer();
  ~QtRenderer();

public slots:
  virtual void updateGL();
};

#endif

qtrenderer.cpp

#include "qtrenderer.h"
QtRenderer::QtRenderer() :
  QGLWidget() {
}

QtRenderer::~QtRenderer() {
}

void QtRenderer::initializeGL() {
  try {
    glext::load_gl_extensions();
  } catch (...) {
    throw std::runtime_error("Failed to load needed extensions.");
  }
}

void QtRenderer::paintGL() {
  swapBuffers();
}

void QtRenderer::updateGL() {
  paintGL();
}

使用

构建此源代码时
gcc (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2)

我收到以下构建错误:

qtrenderer.o: In function `glext::load_gl_extensions()':
/home/mehoggan/Devel/test_gl/./gl_ext.h:28: multiple definition of `glCreateShader'
main.o:/home/mehoggan/Devel/test_gl/./gl_ext.h:28: first defined here

为什么会这样?

2 个答案:

答案 0 :(得分:3)

好吧,标题gl_ext.h包含多次。请记住,#include类似于以复制和粘贴方式将#include语句替换为文件内容。

您应该将load_gl_extensions()的实现放入.cpp文件中,并将声明只放入头文件中。

gl_ext.h:

//...

extern PFNGLCREATESHADERPROC glCreateShader;

namespace glext
{
  bool load_gl_extensions();
}

gl_ext.cpp:

#include "gl_ext.h"

PFNGLCREATESHADERPROC glCreateShader = 0;

namespace glext
{
  bool load_gl_extensions()
  {
    static bool loaded = false;
    if (loaded) {
      return true;
    }
    if (!glCreateShader) {
      glCreateShader = 
        (PFNGLCREATESHADERPROC)(glGetProcAddress("glCreateShader"));
      if (!glCreateShader) {
        throw "Failed to load glCreateShader";
      }
    }
  }
}

extern告诉编译器变量/函数指针(glCreateShader)放在不同的编译单元中(每个.cpp文件被编译为不同的单元)。然后链接器插入变量的正确内存地址。也许您应该对C ++编译和链接的工作方式进行一些研究。

答案 1 :(得分:0)

问题的解决方案包括使方法内联并将函数指针声明为静态。