使用 make 构建时出错:对 `CEGUI::NullRenderer::create()' 的未定义引用
Error building with make: Undefined reference to `CEGUI::NullRenderer::create()'
最近有人让我想起了我小时候玩过的一款游戏(不久前),我想再次尝试 运行。它已经将近十年没有开发了,所以没有一个预构建的包起作用。我获取了游戏的源代码和旧版本的 CEGUI 库并开始工作。
我修复了 make 过程中的一些问题,但现在我遇到了这个错误消息:
/usr/bin/ld: smc-video.o: in function `SMC::cVideo::Init_CEGUI_Fake() const':
video.cpp:107: undefined reference to `CEGUI::NullRenderer::create()'
我对 C++ 没有什么经验,但我设法理解这是一个找不到函数声明的链接器问题。所以我查看了应该有声明的文件,确实有一个创建函数:
/*!
\brief
Create an NullRenderer object
*/
static NullRenderer& create();
但是它不会错过声明吗?我检查过链接器是否在正确的文件中查找函数,因为将 {} 添加到代码中确实可以防止错误(它当然会导致不同的错误),这让我相信 make 没有任何问题。我也在 CEGUINullRenderer.h 的包含中查找声明,但没有找到。 (没有CEGUINullRenderer.cpp)
我试过只从创建函数返回一个 NullRenderer 对象,但这实际上不起作用。我在这里错过了什么?
video.cpp(直到抛出错误的部分):
/***************************************************************************
* video.cpp - General video functions
*
* Copyright (C) 2005 - 2011 Florian Richter
***************************************************************************/
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../video/video.h"
#include "../gui/hud.h"
#include "../user/preferences.h"
#include "../core/framerate.h"
#include "../video/font.h"
#include "../core/game_core.h"
#include "../video/img_settings.h"
#include "../input/mouse.h"
#include "../video/renderer.h"
#include "../core/main.h"
#include "../core/math/utilities.h"
#include "../core/i18n.h"
#include "../core/math/size.h"
#include "../core/filesystem/filesystem.h"
#include "../core/filesystem/resource_manager.h"
#include "../gui/spinner.h"
// SDL
#include "SDL_opengl.h"
// CEGUI
#include "CEGUIDefaultResourceProvider.h"
#include "CEGUIDefaultLogger.h"
#include "CEGUIExceptions.h"
#include "CEGUIWindowFactoryManager.h"
#include "CEGUIImagesetManager.h"
#include "CEGUIFontManager.h"
#include "CEGUIWindowManager.h"
#include "CEGUISchemeManager.h"
#include "falagard/CEGUIFalWidgetLookManager.h"
#include "elements/CEGUIProgressBar.h"
#include "RendererModules/Null/CEGUINullRenderer.h"
// png
#include <png.h>
#ifndef PNG_COLOR_TYPE_RGBA
#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA
#endif
namespace SMC
{
/* *** *** *** *** *** *** *** Video class *** *** *** *** *** *** *** *** *** *** */
cVideo :: cVideo( void )
{
m_opengl_version = 0;
m_double_buffer = 0;
m_rgb_size[0] = 0;
m_rgb_size[1] = 0;
m_rgb_size[2] = 0;
m_default_buffer = GL_BACK;
m_max_texture_size = 512;
m_audio_init_failed = 0;
m_joy_init_failed = 0;
m_geometry_quality = cPreferences::m_geometry_quality_default;
m_texture_quality = cPreferences::m_texture_quality_default;
SDL_VERSION( &wm_info.version );
#ifdef __unix__
glx_context = NULL;
#endif
m_render_thread = boost::thread();
m_initialised = 0;
}
cVideo :: ~cVideo( void )
{
}
void cVideo :: Init_CEGUI_Fake( void ) const
{
// create fake Resource Provider
CEGUI::DefaultResourceProvider *rp = new CEGUI::DefaultResourceProvider();
// set Resource Provider directories
if( CEGUI::System::getDefaultXMLParserName().compare( "XercesParser" ) == 0 )
{
// This is needed for Xerces to specify the schemas location
rp->setResourceGroupDirectory( "schemas", DATA_DIR "/" GAME_SCHEMA_DIR "/" );
}
// get a directory to dump the CEGUI log
#ifdef _WIN32
// fixme : Workaround for std::string to CEGUI::String utf8 conversion. Check again if CEGUI 0.8 works with std::string utf8
CEGUI::String log_dump_dir = (const CEGUI::utf8*)((Get_Temp_Directory() + "cegui.log").c_str());
#else
CEGUI::String log_dump_dir = "/dev/null";
#endif
// create fake system and renderer
pGuiSystem = &CEGUI::System::create( CEGUI::NullRenderer::create(), rp, NULL, NULL, NULL, "", log_dump_dir );
}
CEGUINullRenderer.h:
/***********************************************************************
filename: CEGUINullRenderer.h
created: Fri Jan 15 2010
author: Eugene Marcotte
*************************************************************************/
/***************************************************************************
* Copyright (C) 2004 - 2010 Paul D Turner & The CEGUI Development Team
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
***************************************************************************/
#ifndef _CEGUINullRenderer_h_
#define _CEGUINullRenderer_h_
#include "../../CEGUIRenderer.h"
#include "../../CEGUISize.h"
#include "../../CEGUIVector.h"
#include <vector>
#include <map>
#if (defined( __WIN32__ ) || defined( _WIN32 )) && !defined(CEGUI_STATIC)
# ifdef NULL_GUIRENDERER_EXPORTS
# define NULL_GUIRENDERER_API __declspec(dllexport)
# else
# define NULL_GUIRENDERER_API __declspec(dllimport)
# endif
#else
# define NULL_GUIRENDERER_API
#endif
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable : 4251)
#endif
// Start of CEGUI namespace section
namespace CEGUI
{
class NullGeometryBuffer;
class NullTexture;
class NullRenderTarget;
//! CEGUI::Renderer implementation for no particular engine
class NULL_GUIRENDERER_API NullRenderer : public Renderer
{
public:
/*!
\brief
Convenience function that creates all the necessary objects
then initialises the CEGUI system with them.
This will create and initialise the following objects for you:
- CEGUI::NullRenderer
- CEGUI::DefaultResourceProvider
- CEGUI::System
\return
Reference to the CEGUI::NullRenderer object that was created.
*/
static NullRenderer& bootstrapSystem();
/*!
\brief
Convenience function to cleanup the CEGUI system and related objects
that were created by calling the bootstrapSystem function.
This function will destroy the following objects for you:
- CEGUI::System
- CEGUI::DefaultResourceProvider
- CEGUI::NullRenderer
\note
If you did not initialise CEGUI by calling the bootstrapSystem function,
you should \e not call this, but rather delete any objects you created
manually.
*/
static void destroySystem();
/*!
\brief
Create an NullRenderer object
*/
static NullRenderer& create();
//! destory an NullRenderer object.
static void destroy(NullRenderer& renderer);
// implement CEGUI::Renderer interface
RenderingRoot& getDefaultRenderingRoot();
GeometryBuffer& createGeometryBuffer();
void destroyGeometryBuffer(const GeometryBuffer& buffer);
void destroyAllGeometryBuffers();
TextureTarget* createTextureTarget();
void destroyTextureTarget(TextureTarget* target);
void destroyAllTextureTargets();
Texture& createTexture();
Texture& createTexture(const String& filename, const String& resourceGroup);
Texture& createTexture(const Size& size);
void destroyTexture(Texture& texture);
void destroyAllTextures();
void beginRendering();
void endRendering();
void setDisplaySize(const Size& sz);
const Size& getDisplaySize() const;
const Vector2& getDisplayDPI() const;
uint getMaxTextureSize() const;
const String& getIdentifierString() const;
protected:
//! default constructor.
NullRenderer();
//! common construction things.
void constructor_impl();
//! destructor.
virtual ~NullRenderer();
//! String holding the renderer identification text.
static String d_rendererID;
//! What the renderer considers to be the current display size.
Size d_displaySize;
//! What the renderer considers to be the current display DPI resolution.
Vector2 d_displayDPI;
//! The default rendering root object
RenderingRoot* d_defaultRoot;
//! The default RenderTarget (used by d_defaultRoot)
NullRenderTarget* d_defaultTarget;
//! container type used to hold TextureTargets we create.
typedef std::vector<TextureTarget*> TextureTargetList;
//! Container used to track texture targets.
TextureTargetList d_textureTargets;
//! container type used to hold GeometryBuffers we create.
typedef std::vector<NullGeometryBuffer*> GeometryBufferList;
//! Container used to track geometry buffers.
GeometryBufferList d_geometryBuffers;
//! container type used to hold Textures we create.
typedef std::vector<NullTexture*> TextureList;
//! Container used to track textures.
TextureList d_textures;
//! What the renderer thinks the max texture size is.
uint d_maxTextureSize;
};
} // End of CEGUI namespace section
#if defined(_MSC_VER)
# pragma warning(pop)
#endif
#endif // end of guard _CEGUINullRenderer_h_
你已经声明了它,这意味着编译器很乐意编译它。声明就像函数的名称:编译器知道函数存在并且可以编译调用它的代码。
但是为了link它,你必须在那个函数的定义(实现)中link。 linker 告诉你它没有你声明的函数的实际实现。
很可能你的 link 行是错误的,几乎可以肯定你根本就忘了把库放在 link 行上,或者你把它放在了错误的地方,但是因为你没有如果不向我们提供有关 运行 生成该错误消息的 link 命令的任何信息,或者您使用 link 的 makefile 规则,我们将无能为力。
最近有人让我想起了我小时候玩过的一款游戏(不久前),我想再次尝试 运行。它已经将近十年没有开发了,所以没有一个预构建的包起作用。我获取了游戏的源代码和旧版本的 CEGUI 库并开始工作。
我修复了 make 过程中的一些问题,但现在我遇到了这个错误消息:
/usr/bin/ld: smc-video.o: in function `SMC::cVideo::Init_CEGUI_Fake() const':
video.cpp:107: undefined reference to `CEGUI::NullRenderer::create()'
我对 C++ 没有什么经验,但我设法理解这是一个找不到函数声明的链接器问题。所以我查看了应该有声明的文件,确实有一个创建函数:
/*!
\brief
Create an NullRenderer object
*/
static NullRenderer& create();
但是它不会错过声明吗?我检查过链接器是否在正确的文件中查找函数,因为将 {} 添加到代码中确实可以防止错误(它当然会导致不同的错误),这让我相信 make 没有任何问题。我也在 CEGUINullRenderer.h 的包含中查找声明,但没有找到。 (没有CEGUINullRenderer.cpp)
我试过只从创建函数返回一个 NullRenderer 对象,但这实际上不起作用。我在这里错过了什么?
video.cpp(直到抛出错误的部分):
/***************************************************************************
* video.cpp - General video functions
*
* Copyright (C) 2005 - 2011 Florian Richter
***************************************************************************/
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../video/video.h"
#include "../gui/hud.h"
#include "../user/preferences.h"
#include "../core/framerate.h"
#include "../video/font.h"
#include "../core/game_core.h"
#include "../video/img_settings.h"
#include "../input/mouse.h"
#include "../video/renderer.h"
#include "../core/main.h"
#include "../core/math/utilities.h"
#include "../core/i18n.h"
#include "../core/math/size.h"
#include "../core/filesystem/filesystem.h"
#include "../core/filesystem/resource_manager.h"
#include "../gui/spinner.h"
// SDL
#include "SDL_opengl.h"
// CEGUI
#include "CEGUIDefaultResourceProvider.h"
#include "CEGUIDefaultLogger.h"
#include "CEGUIExceptions.h"
#include "CEGUIWindowFactoryManager.h"
#include "CEGUIImagesetManager.h"
#include "CEGUIFontManager.h"
#include "CEGUIWindowManager.h"
#include "CEGUISchemeManager.h"
#include "falagard/CEGUIFalWidgetLookManager.h"
#include "elements/CEGUIProgressBar.h"
#include "RendererModules/Null/CEGUINullRenderer.h"
// png
#include <png.h>
#ifndef PNG_COLOR_TYPE_RGBA
#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA
#endif
namespace SMC
{
/* *** *** *** *** *** *** *** Video class *** *** *** *** *** *** *** *** *** *** */
cVideo :: cVideo( void )
{
m_opengl_version = 0;
m_double_buffer = 0;
m_rgb_size[0] = 0;
m_rgb_size[1] = 0;
m_rgb_size[2] = 0;
m_default_buffer = GL_BACK;
m_max_texture_size = 512;
m_audio_init_failed = 0;
m_joy_init_failed = 0;
m_geometry_quality = cPreferences::m_geometry_quality_default;
m_texture_quality = cPreferences::m_texture_quality_default;
SDL_VERSION( &wm_info.version );
#ifdef __unix__
glx_context = NULL;
#endif
m_render_thread = boost::thread();
m_initialised = 0;
}
cVideo :: ~cVideo( void )
{
}
void cVideo :: Init_CEGUI_Fake( void ) const
{
// create fake Resource Provider
CEGUI::DefaultResourceProvider *rp = new CEGUI::DefaultResourceProvider();
// set Resource Provider directories
if( CEGUI::System::getDefaultXMLParserName().compare( "XercesParser" ) == 0 )
{
// This is needed for Xerces to specify the schemas location
rp->setResourceGroupDirectory( "schemas", DATA_DIR "/" GAME_SCHEMA_DIR "/" );
}
// get a directory to dump the CEGUI log
#ifdef _WIN32
// fixme : Workaround for std::string to CEGUI::String utf8 conversion. Check again if CEGUI 0.8 works with std::string utf8
CEGUI::String log_dump_dir = (const CEGUI::utf8*)((Get_Temp_Directory() + "cegui.log").c_str());
#else
CEGUI::String log_dump_dir = "/dev/null";
#endif
// create fake system and renderer
pGuiSystem = &CEGUI::System::create( CEGUI::NullRenderer::create(), rp, NULL, NULL, NULL, "", log_dump_dir );
}
CEGUINullRenderer.h:
/***********************************************************************
filename: CEGUINullRenderer.h
created: Fri Jan 15 2010
author: Eugene Marcotte
*************************************************************************/
/***************************************************************************
* Copyright (C) 2004 - 2010 Paul D Turner & The CEGUI Development Team
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
***************************************************************************/
#ifndef _CEGUINullRenderer_h_
#define _CEGUINullRenderer_h_
#include "../../CEGUIRenderer.h"
#include "../../CEGUISize.h"
#include "../../CEGUIVector.h"
#include <vector>
#include <map>
#if (defined( __WIN32__ ) || defined( _WIN32 )) && !defined(CEGUI_STATIC)
# ifdef NULL_GUIRENDERER_EXPORTS
# define NULL_GUIRENDERER_API __declspec(dllexport)
# else
# define NULL_GUIRENDERER_API __declspec(dllimport)
# endif
#else
# define NULL_GUIRENDERER_API
#endif
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable : 4251)
#endif
// Start of CEGUI namespace section
namespace CEGUI
{
class NullGeometryBuffer;
class NullTexture;
class NullRenderTarget;
//! CEGUI::Renderer implementation for no particular engine
class NULL_GUIRENDERER_API NullRenderer : public Renderer
{
public:
/*!
\brief
Convenience function that creates all the necessary objects
then initialises the CEGUI system with them.
This will create and initialise the following objects for you:
- CEGUI::NullRenderer
- CEGUI::DefaultResourceProvider
- CEGUI::System
\return
Reference to the CEGUI::NullRenderer object that was created.
*/
static NullRenderer& bootstrapSystem();
/*!
\brief
Convenience function to cleanup the CEGUI system and related objects
that were created by calling the bootstrapSystem function.
This function will destroy the following objects for you:
- CEGUI::System
- CEGUI::DefaultResourceProvider
- CEGUI::NullRenderer
\note
If you did not initialise CEGUI by calling the bootstrapSystem function,
you should \e not call this, but rather delete any objects you created
manually.
*/
static void destroySystem();
/*!
\brief
Create an NullRenderer object
*/
static NullRenderer& create();
//! destory an NullRenderer object.
static void destroy(NullRenderer& renderer);
// implement CEGUI::Renderer interface
RenderingRoot& getDefaultRenderingRoot();
GeometryBuffer& createGeometryBuffer();
void destroyGeometryBuffer(const GeometryBuffer& buffer);
void destroyAllGeometryBuffers();
TextureTarget* createTextureTarget();
void destroyTextureTarget(TextureTarget* target);
void destroyAllTextureTargets();
Texture& createTexture();
Texture& createTexture(const String& filename, const String& resourceGroup);
Texture& createTexture(const Size& size);
void destroyTexture(Texture& texture);
void destroyAllTextures();
void beginRendering();
void endRendering();
void setDisplaySize(const Size& sz);
const Size& getDisplaySize() const;
const Vector2& getDisplayDPI() const;
uint getMaxTextureSize() const;
const String& getIdentifierString() const;
protected:
//! default constructor.
NullRenderer();
//! common construction things.
void constructor_impl();
//! destructor.
virtual ~NullRenderer();
//! String holding the renderer identification text.
static String d_rendererID;
//! What the renderer considers to be the current display size.
Size d_displaySize;
//! What the renderer considers to be the current display DPI resolution.
Vector2 d_displayDPI;
//! The default rendering root object
RenderingRoot* d_defaultRoot;
//! The default RenderTarget (used by d_defaultRoot)
NullRenderTarget* d_defaultTarget;
//! container type used to hold TextureTargets we create.
typedef std::vector<TextureTarget*> TextureTargetList;
//! Container used to track texture targets.
TextureTargetList d_textureTargets;
//! container type used to hold GeometryBuffers we create.
typedef std::vector<NullGeometryBuffer*> GeometryBufferList;
//! Container used to track geometry buffers.
GeometryBufferList d_geometryBuffers;
//! container type used to hold Textures we create.
typedef std::vector<NullTexture*> TextureList;
//! Container used to track textures.
TextureList d_textures;
//! What the renderer thinks the max texture size is.
uint d_maxTextureSize;
};
} // End of CEGUI namespace section
#if defined(_MSC_VER)
# pragma warning(pop)
#endif
#endif // end of guard _CEGUINullRenderer_h_
你已经声明了它,这意味着编译器很乐意编译它。声明就像函数的名称:编译器知道函数存在并且可以编译调用它的代码。
但是为了link它,你必须在那个函数的定义(实现)中link。 linker 告诉你它没有你声明的函数的实际实现。
很可能你的 link 行是错误的,几乎可以肯定你根本就忘了把库放在 link 行上,或者你把它放在了错误的地方,但是因为你没有如果不向我们提供有关 运行 生成该错误消息的 link 命令的任何信息,或者您使用 link 的 makefile 规则,我们将无能为力。