1

I have exposed lots of SFML classes to Lua with LuaBridge, and I have tested most of the classes and they work great (sf::RectangleShape, sf::Texture etc.) but, I'm having issues with sf::Font and sf::Text. First, my C++ code to expose sf::Font and 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");
}

If I create a lua script that use Text and Font I get a Segmentation Fault, sometimes. By this I mean that I only get the error when I draw the Text object, if I set the font.

Script:

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

Update:

After testing with other SFML classes, it appears that this isn't an issue for sf::Texture and sf::Sprite/sf::RectangleShape/sf::CircleShape etc. This tells me that it is a sf::Font problem, rather than the reference being deleted

Related Question about LuaBridge and SFML

Community
  • 1
  • 1
Ben Hollier
  • 585
  • 2
  • 11
  • 32
  • The trick is not to post a question that can't be answered, but to reduce the amount of code needed to answer the question... you should post all the code that's required to reproduce the problem in full. – Puppy Jul 26 '15 at 18:04
  • @Puppy The only code that is missing is running the script, I can add it in though – Ben Hollier Jul 26 '15 at 18:05
  • @Puppy The code has been added, it was a little bit harder than expected, because I had to expose more classes than I first thought (like `sf::Window` and `sf::Vector2`) – Ben Hollier Jul 26 '15 at 18:51

1 Answers1

0

The way I found to fix the problem (thanks to the SFML Forums for the answer) was to change this line of code in TextWrap:

void setFont(const sf::Font& newFont) {member.setFont(newFont);}

To this:

void setFont(const sf::Font* newFont) {member.setFont(*newFont);}

According to the forum, the reason this was a problem is because Lua is based off of C instead of C++, so doesn't know about pointers. So by making the argument a pointer, then dereferencing the pointer, I effectively fix the problem

Ben Hollier
  • 585
  • 2
  • 11
  • 32