在 Lua 中绘制 sf::Text 对象时出现分段错误
Segmentation Fault when drawing a sf::Text object in Lua
我已经使用 LuaBridge 公开了很多 SFML 类 到 Lua,我已经测试了大部分 类,它们工作得很好(sf::RectangleShape
、sf::Texture
等)但是,我遇到了 sf::Font
和 sf::Text
的问题。首先,我的 C++ 代码公开 sf::Font
和 sf::Text
:
#include <string>
#include <SFML/Graphics.hpp>
#include <lua.hpp>
#include <LuaBridge.h>
//Wrapper for sf::Text:
class TextWrap
{
private:
sf::Text member;
public:
void setCharacterSize(const int& newSize) {member.setCharacterSize(newSize);}
int getCharacterSize() {return member.getCharacterSize();}
void setColor(const sf::Color& newColor) {member.setColor(newColor);}
sf::Color getColor() {return member.getColor();}
void setFont(const sf::Font& newFont) {member.setFont(newFont);}
const sf::Font* getFont() {return member.getFont();}
void setPosition(const sf::Vector2f& newPosition) {member.setPosition(newPosition);}
sf::Vector2f getPosition() {return member.getPosition();}
void setRotation(const float& rotation) {member.setRotation(rotation);}
float getRotation() {return member.getRotation();}
void setScale(const sf::Vector2f& newScale) {member.setScale(newScale);}
sf::Vector2f getScale() {return member.getScale();}
void setString(const std::string& text) {member.setString(text);}
std::string getString() {return member.getString();}
void move(const sf::Vector2f& movePos) {member.move(movePos);}
void rotate(const float& rotation) {member.rotate(rotation);}
void scale(const sf::Vector2f& scaleAmount) {member.scale(scaleAmount);}
sf::Text getMember() {return member;}
};
class WindowWrap
{
private:
sf::RenderWindow member;
public:
void createWindowed(const unsigned int width, const unsigned int height, const std::string& title) {member.create(sf::VideoMode(width, height), title);}
void createFullscreen(const unsigned int width, const unsigned int height, const std::string& title) {member.create(sf::VideoMode(width, height), title, sf::Style::Fullscreen);}
void createSplash(const unsigned int width, const unsigned int height) {member.create(sf::VideoMode(width, height), "Splash");}
void close() {member.close();}
void clear(const sf::Color& clearColour) {member.clear(clearColour);}
void display() {member.display();}
void drawText(TextWrap& text) {member.draw(text.getMember());}
void setPosition(const sf::Vector2i& newPosition) {member.setPosition(newPosition);}
sf::Vector2i getPosition() {return member.getPosition();}
void setSize(const sf::Vector2u& newSize) {member.setSize(newSize);}
sf::Vector2u getSize() {return member.getSize();}
bool isOpen() {return member.isOpen();}
sf::Vector2i mapCoordsToPixel(const sf::Vector2f& point) {return member.mapCoordsToPixel(point);}
sf::Vector2f mapPixelToCoords(const sf::Vector2i& point) {return member.mapPixelToCoords(point);}
bool setActive() {return member.setActive();}
void setFramerateLimit(const unsigned int& limit) {member.setFramerateLimit(limit);}
void setJoystickThreshold(const float& threshold) {member.setJoystickThreshold(threshold);}
void setKeyRepeatEnabled(bool enabled) {member.setKeyRepeatEnabled(enabled);}
void setVerticalSyncEnabled(bool enabled) {member.setVerticalSyncEnabled(enabled);}
void setMouseCursorVisible(bool enabled) {member.setMouseCursorVisible(enabled);}
void setTitle(const std::string& title) {member.setTitle(title);}
void setVisible(const bool& enabled) {member.setVisible(enabled);}
};
int main()
{
lua_State* L = luaL_newstate();
luaL_openlibs(L);
luabridge::getGlobalNamespace(L)
.beginClass<sf::Vector2f>("Vector2f")
.addConstructor<void(*)(float, float)>()
.addData("x", &sf::Vector2f::x)
.addData("y", &sf::Vector2f::y)
.endClass()
.beginClass<sf::Vector2i>("Vector2i")
.addConstructor<void(*)(int, int)>()
.addData("x", &sf::Vector2i::x)
.addData("y", &sf::Vector2i::y)
.endClass()
.beginClass<sf::Vector2u>("Vector2u")
.addConstructor<void(*)(unsigned int, unsigned int)>()
.addData("x", &sf::Vector2u::x)
.addData("y", &sf::Vector2u::y)
.endClass()
.beginClass<sf::IntRect>("IntRect")
.addConstructor<void(*)(int, int, int, int)>()
.addData("top", &sf::IntRect::top)
.addData("left", &sf::IntRect::left)
.addData("height", &sf::IntRect::height)
.addData("width", &sf::IntRect::width)
.endClass()
.beginClass<sf::FloatRect>("FloatRect")
.addConstructor<void(*)(float, float, float, float)>()
.addData("top", &sf::FloatRect::top)
.addData("left", &sf::FloatRect::left)
.addData("height", &sf::FloatRect::height)
.addData("width", &sf::FloatRect::width)
.endClass()
.beginClass<sf::Color>("Color")
.addConstructor<void(*)(unsigned int, unsigned int, unsigned int, unsigned int)>()
.addData("r", &sf::Color::r)
.addData("g", &sf::Color::g)
.addData("b", &sf::Color::b)
.addData("a", &sf::Color::a)
.endClass()
.beginClass<sf::Font>("Font")
.addConstructor<void(*)(void)>()
.addFunction("loadFromFile", &sf::Font::loadFromFile)
.endClass()
.beginClass<TextWrap>("Text")
.addConstructor<void(*)(void)>()
.addFunction("setCharacterSize", &TextWrap::setCharacterSize)
.addFunction("getCharacterSize", &TextWrap::getCharacterSize)
.addFunction("setColor", &TextWrap::setColor)
.addFunction("getColor", &TextWrap::getColor)
.addFunction("setFont", &TextWrap::setFont)
.addFunction("getFont", &TextWrap::getFont)
.addFunction("setPosition", &TextWrap::setPosition)
.addFunction("getPosition", &TextWrap::getPosition)
.addFunction("setRotation", &TextWrap::setRotation)
.addFunction("getRotation", &TextWrap::getRotation)
.addFunction("setScale", &TextWrap::setScale)
.addFunction("getScale", &TextWrap::getScale)
.addFunction("setString", &TextWrap::setString)
.addFunction("getString", &TextWrap::getString)
.addFunction("move", &TextWrap::move)
.addFunction("rotate", &TextWrap::rotate)
.addFunction("scale", &TextWrap::scale)
.endClass()
.beginClass<WindowWrap>("Window")
.addConstructor<void(*)(void)>()
.addFunction("createWindowed", &WindowWrap::createWindowed)
.addFunction("createFullscreen", &WindowWrap::createFullscreen)
.addFunction("createSplash", &WindowWrap::createSplash)
.addFunction("close", &WindowWrap::close)
.addFunction("clear", &WindowWrap::clear)
.addFunction("display", &WindowWrap::display)
.addFunction("drawText", &WindowWrap::drawText)
.addFunction("setPosition", &WindowWrap::setPosition)
.addFunction("getPosition", &WindowWrap::getPosition)
.addFunction("setSize", &WindowWrap::setSize)
.addFunction("getSize", &WindowWrap::getSize)
.addFunction("isOpen", &WindowWrap::isOpen)
.addFunction("mapCoordsToPixel", &WindowWrap::mapCoordsToPixel)
.addFunction("mapPixelToCoords", &WindowWrap::mapPixelToCoords)
.addFunction("setActive", &WindowWrap::setActive)
.addFunction("setFramerateLimit", &WindowWrap::setFramerateLimit)
.addFunction("setKeyRepeatEnabled", &WindowWrap::setKeyRepeatEnabled)
.addFunction("setVerticalSyncEnabled", &WindowWrap::setVerticalSyncEnabled)
.addFunction("setMouseCursorVisible", &WindowWrap::setMouseCursorVisible)
.addFunction("setTitle", &WindowWrap::setTitle)
.addFunction("setVisible", &WindowWrap::setVisible)
.endClass();
WindowWrap mainWindow; //This is defined here so C++ knows if the main application is open
mainWindow.createWindowed(800, 600, "Lua Test");
luabridge::push(L, &mainWindow);
lua_setglobal(L, "mainWindow");
luaL_dofile(L, "./script.lua");
}
如果我创建一个使用 Text
和 Font
的 lua 脚本,我会遇到分段错误,有时 。我的意思是,如果我设置了字体,我只会在绘制 Text 对象时出现错误。
脚本:
text = Text();
text:setCharacterSize(16);
text:setPosition(Vector2f(100, 100));
text:setColor(Color(255,255,255,255));
text:setString("Hello World");
font = Font();
font:loadFromFile("./font.ttf");
text:setFont(font); --If I remove this I don't get a Segmentation Fault
mainWindow:drawText(text); --But the Segmentation Fault happens here
更新:
在使用其他 SFML 类 进行测试后,这似乎不是 sf::Texture
和 sf::Sprite
/sf::RectangleShape
/sf::CircleShape
等的问题.这告诉我这是一个sf::Font
问题,而不是引用被删除
我发现解决问题的方法(感谢 SFML Forums 的回答)是更改 TextWrap
:
中的这行代码
void setFont(const sf::Font& newFont) {member.setFont(newFont);}
为此:
void setFont(const sf::Font* newFont) {member.setFont(*newFont);}
根据论坛,这是一个问题的原因是因为 Lua 基于 C 而不是 C++,所以不了解指针。因此,通过将参数设为指针,然后取消引用指针,我有效地解决了问题
我已经使用 LuaBridge 公开了很多 SFML 类 到 Lua,我已经测试了大部分 类,它们工作得很好(sf::RectangleShape
、sf::Texture
等)但是,我遇到了 sf::Font
和 sf::Text
的问题。首先,我的 C++ 代码公开 sf::Font
和 sf::Text
:
#include <string>
#include <SFML/Graphics.hpp>
#include <lua.hpp>
#include <LuaBridge.h>
//Wrapper for sf::Text:
class TextWrap
{
private:
sf::Text member;
public:
void setCharacterSize(const int& newSize) {member.setCharacterSize(newSize);}
int getCharacterSize() {return member.getCharacterSize();}
void setColor(const sf::Color& newColor) {member.setColor(newColor);}
sf::Color getColor() {return member.getColor();}
void setFont(const sf::Font& newFont) {member.setFont(newFont);}
const sf::Font* getFont() {return member.getFont();}
void setPosition(const sf::Vector2f& newPosition) {member.setPosition(newPosition);}
sf::Vector2f getPosition() {return member.getPosition();}
void setRotation(const float& rotation) {member.setRotation(rotation);}
float getRotation() {return member.getRotation();}
void setScale(const sf::Vector2f& newScale) {member.setScale(newScale);}
sf::Vector2f getScale() {return member.getScale();}
void setString(const std::string& text) {member.setString(text);}
std::string getString() {return member.getString();}
void move(const sf::Vector2f& movePos) {member.move(movePos);}
void rotate(const float& rotation) {member.rotate(rotation);}
void scale(const sf::Vector2f& scaleAmount) {member.scale(scaleAmount);}
sf::Text getMember() {return member;}
};
class WindowWrap
{
private:
sf::RenderWindow member;
public:
void createWindowed(const unsigned int width, const unsigned int height, const std::string& title) {member.create(sf::VideoMode(width, height), title);}
void createFullscreen(const unsigned int width, const unsigned int height, const std::string& title) {member.create(sf::VideoMode(width, height), title, sf::Style::Fullscreen);}
void createSplash(const unsigned int width, const unsigned int height) {member.create(sf::VideoMode(width, height), "Splash");}
void close() {member.close();}
void clear(const sf::Color& clearColour) {member.clear(clearColour);}
void display() {member.display();}
void drawText(TextWrap& text) {member.draw(text.getMember());}
void setPosition(const sf::Vector2i& newPosition) {member.setPosition(newPosition);}
sf::Vector2i getPosition() {return member.getPosition();}
void setSize(const sf::Vector2u& newSize) {member.setSize(newSize);}
sf::Vector2u getSize() {return member.getSize();}
bool isOpen() {return member.isOpen();}
sf::Vector2i mapCoordsToPixel(const sf::Vector2f& point) {return member.mapCoordsToPixel(point);}
sf::Vector2f mapPixelToCoords(const sf::Vector2i& point) {return member.mapPixelToCoords(point);}
bool setActive() {return member.setActive();}
void setFramerateLimit(const unsigned int& limit) {member.setFramerateLimit(limit);}
void setJoystickThreshold(const float& threshold) {member.setJoystickThreshold(threshold);}
void setKeyRepeatEnabled(bool enabled) {member.setKeyRepeatEnabled(enabled);}
void setVerticalSyncEnabled(bool enabled) {member.setVerticalSyncEnabled(enabled);}
void setMouseCursorVisible(bool enabled) {member.setMouseCursorVisible(enabled);}
void setTitle(const std::string& title) {member.setTitle(title);}
void setVisible(const bool& enabled) {member.setVisible(enabled);}
};
int main()
{
lua_State* L = luaL_newstate();
luaL_openlibs(L);
luabridge::getGlobalNamespace(L)
.beginClass<sf::Vector2f>("Vector2f")
.addConstructor<void(*)(float, float)>()
.addData("x", &sf::Vector2f::x)
.addData("y", &sf::Vector2f::y)
.endClass()
.beginClass<sf::Vector2i>("Vector2i")
.addConstructor<void(*)(int, int)>()
.addData("x", &sf::Vector2i::x)
.addData("y", &sf::Vector2i::y)
.endClass()
.beginClass<sf::Vector2u>("Vector2u")
.addConstructor<void(*)(unsigned int, unsigned int)>()
.addData("x", &sf::Vector2u::x)
.addData("y", &sf::Vector2u::y)
.endClass()
.beginClass<sf::IntRect>("IntRect")
.addConstructor<void(*)(int, int, int, int)>()
.addData("top", &sf::IntRect::top)
.addData("left", &sf::IntRect::left)
.addData("height", &sf::IntRect::height)
.addData("width", &sf::IntRect::width)
.endClass()
.beginClass<sf::FloatRect>("FloatRect")
.addConstructor<void(*)(float, float, float, float)>()
.addData("top", &sf::FloatRect::top)
.addData("left", &sf::FloatRect::left)
.addData("height", &sf::FloatRect::height)
.addData("width", &sf::FloatRect::width)
.endClass()
.beginClass<sf::Color>("Color")
.addConstructor<void(*)(unsigned int, unsigned int, unsigned int, unsigned int)>()
.addData("r", &sf::Color::r)
.addData("g", &sf::Color::g)
.addData("b", &sf::Color::b)
.addData("a", &sf::Color::a)
.endClass()
.beginClass<sf::Font>("Font")
.addConstructor<void(*)(void)>()
.addFunction("loadFromFile", &sf::Font::loadFromFile)
.endClass()
.beginClass<TextWrap>("Text")
.addConstructor<void(*)(void)>()
.addFunction("setCharacterSize", &TextWrap::setCharacterSize)
.addFunction("getCharacterSize", &TextWrap::getCharacterSize)
.addFunction("setColor", &TextWrap::setColor)
.addFunction("getColor", &TextWrap::getColor)
.addFunction("setFont", &TextWrap::setFont)
.addFunction("getFont", &TextWrap::getFont)
.addFunction("setPosition", &TextWrap::setPosition)
.addFunction("getPosition", &TextWrap::getPosition)
.addFunction("setRotation", &TextWrap::setRotation)
.addFunction("getRotation", &TextWrap::getRotation)
.addFunction("setScale", &TextWrap::setScale)
.addFunction("getScale", &TextWrap::getScale)
.addFunction("setString", &TextWrap::setString)
.addFunction("getString", &TextWrap::getString)
.addFunction("move", &TextWrap::move)
.addFunction("rotate", &TextWrap::rotate)
.addFunction("scale", &TextWrap::scale)
.endClass()
.beginClass<WindowWrap>("Window")
.addConstructor<void(*)(void)>()
.addFunction("createWindowed", &WindowWrap::createWindowed)
.addFunction("createFullscreen", &WindowWrap::createFullscreen)
.addFunction("createSplash", &WindowWrap::createSplash)
.addFunction("close", &WindowWrap::close)
.addFunction("clear", &WindowWrap::clear)
.addFunction("display", &WindowWrap::display)
.addFunction("drawText", &WindowWrap::drawText)
.addFunction("setPosition", &WindowWrap::setPosition)
.addFunction("getPosition", &WindowWrap::getPosition)
.addFunction("setSize", &WindowWrap::setSize)
.addFunction("getSize", &WindowWrap::getSize)
.addFunction("isOpen", &WindowWrap::isOpen)
.addFunction("mapCoordsToPixel", &WindowWrap::mapCoordsToPixel)
.addFunction("mapPixelToCoords", &WindowWrap::mapPixelToCoords)
.addFunction("setActive", &WindowWrap::setActive)
.addFunction("setFramerateLimit", &WindowWrap::setFramerateLimit)
.addFunction("setKeyRepeatEnabled", &WindowWrap::setKeyRepeatEnabled)
.addFunction("setVerticalSyncEnabled", &WindowWrap::setVerticalSyncEnabled)
.addFunction("setMouseCursorVisible", &WindowWrap::setMouseCursorVisible)
.addFunction("setTitle", &WindowWrap::setTitle)
.addFunction("setVisible", &WindowWrap::setVisible)
.endClass();
WindowWrap mainWindow; //This is defined here so C++ knows if the main application is open
mainWindow.createWindowed(800, 600, "Lua Test");
luabridge::push(L, &mainWindow);
lua_setglobal(L, "mainWindow");
luaL_dofile(L, "./script.lua");
}
如果我创建一个使用 Text
和 Font
的 lua 脚本,我会遇到分段错误,有时 。我的意思是,如果我设置了字体,我只会在绘制 Text 对象时出现错误。
脚本:
text = Text();
text:setCharacterSize(16);
text:setPosition(Vector2f(100, 100));
text:setColor(Color(255,255,255,255));
text:setString("Hello World");
font = Font();
font:loadFromFile("./font.ttf");
text:setFont(font); --If I remove this I don't get a Segmentation Fault
mainWindow:drawText(text); --But the Segmentation Fault happens here
更新:
在使用其他 SFML 类 进行测试后,这似乎不是 sf::Texture
和 sf::Sprite
/sf::RectangleShape
/sf::CircleShape
等的问题.这告诉我这是一个sf::Font
问题,而不是引用被删除
我发现解决问题的方法(感谢 SFML Forums 的回答)是更改 TextWrap
:
void setFont(const sf::Font& newFont) {member.setFont(newFont);}
为此:
void setFont(const sf::Font* newFont) {member.setFont(*newFont);}
根据论坛,这是一个问题的原因是因为 Lua 基于 C 而不是 C++,所以不了解指针。因此,通过将参数设为指针,然后取消引用指针,我有效地解决了问题