Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: C API Limitations  (Read 6370 times)

0 Members and 1 Guest are viewing this topic.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11038
    • View Profile
    • development blog
    • Email
C API Limitations
« on: March 18, 2022, 03:55:34 pm »
Someone reported this on Discord and I believe, I've run into it sometime before, essentially the CSFML API is limited in regards to, that you can't cast an sfRenderWindow* to an sfWindow* which leaves APIs such as the sfMouse_getPosition(const sfWindow* relativeTo) unusable if you have an sfRenderWindow*.

Should we simply accept this limitation or are there alternatives that we could use?

The most natural one of just adding an additional "overload" doesn't work, because the sfMouse_* functions exist in the window module and the sfRenderWindow is part of the graphics module. It would only work if it was additionally implemented in the graphics module.

Another possibility, which I don't know if would even work, is to have an sfRenderWindow_toWindow or similar casting function, that down casts in C++ from sf::RenderWindow to sf::Window. What I'm unsure about, is whether we can use "safely" use the resulting sfWindow* structure, since we now have two references to the same window instance.

Any other ideas?
« Last Edit: March 18, 2022, 03:57:13 pm by eXpl0it3r »
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: C API Limitations
« Reply #1 on: March 19, 2022, 10:46:53 pm »
When looking at sfWindow and sfRenderWindow, they are defined like this:

struct sfWindow
{
    sf::Window This;
};

struct sfRenderWindow
{
    sf::RenderWindow This;
    sfView           DefaultView;
    sfView           CurrentView;
};

This is already the first problem -- we store a concrete sf::Window value, which is not polymorphic. Instead, we should store sf::Window*, which can point to a sf::RenderWindow behind the scenes (more about memory management later).

Once we have that, an upcast could be implemented:
sfWindow* sfRenderWindow_upcast(sfRenderWindow* renderWindow)
{
    sfWindow window; // assuming C++03 no init-list
    window.This = &renderWindow->This; // 'This' has type sf::Window*

    return window;
}

Memory management
Memory management and ownership makes this a bit trickier. Normally, every sfWindow is created using its create and destroyed using its destroy function. Manual, but very straightforward semantics.

Now, it would be possible that a sfWindow actually points to a sfRenderWindow -- so who should destroy it? One could attempt some std::shared_ptr tricks, however that doesn't work well with C -- copying a struct is always a bytewise copy, so ref-counts would need to be managed manually. There is no win with smart pointers here.

We have two options: either we allow polymorphic destruction in sfWindow_destroy or we don't.
If we don't, we should probably have a runtime check like:
extern "C" void sfWindow_destroy(sf::Window *window) {
    assert(dynamic_cast<sf::RenderWindow*>(window.This) == nullptr);

    delete window.This;
    delete window;
}

(Not sure if this works dependency-wise; since RenderWindow is in Graphics. Of course, there could in the future also be other derived classes. Maybe typeid would be safer, or a bool flag sfWindow::isUpcast).
« Last Edit: March 19, 2022, 10:50:18 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

CrimsonLaceStudio

  • Newbie
  • *
  • Posts: 3
  • Yuki's favorite code monkey
    • View Profile
    • FX-Unit Yuki
    • Email
Re: C API Limitations
« Reply #2 on: May 14, 2022, 02:39:50 pm »
Hi eXpl0it3r, I don't know if you ever resolved this, but I ran into a similar issue when trying to use the mouse pointer with a renderwindow. As it's not mentioned in the mouse docs, I found that the renderwindow api has its own version called sfMouse_getPositionRenderWindow. My apologies if you already got this solved but figured I'd offer a hand if need be. Be well. :)
I code the Yuki things...

Tojot

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: C API Limitations
« Reply #3 on: November 06, 2022, 09:44:47 pm »
I would of course never ever recommend doing that … but …

In this specific case, with the specific memory layout we have today, a forced cast from sfRenderWindow* to sfWindow* should end up pointing to the exact slice of the sf::RenderWindow that looks like a wrapped sf::Window.

I wouldn’t want to maintain code like this over the long term, but if for whatever reason you would want to keep the sf objects directly embedded inside the struct, it should work.