Independence of render and window systems with connection through window handle - c++

Let's say we have interface window_creator that responsible for creation of windows. For simplicity it looks like this:
struct window_creator
{
virtual ~window_creator(){}
handle create_window(size_t width, size_t height, bool fullscreen);
};
Also, we have interface for render system that is responsible for rendering in window created by window_creator. It has, for simplicity, following code:
struct render_system
{
virtual ~render_system(){}
void create(handle window_handle);
};
Also, we have 2 implementations for window_creator interface:
struct windows7_creator : public window_creator
{
handle create_window(size_t width, size_t height, bool fullscreen) override {
//calls CreateWindow and returns HWND
}
};
struct macos_creator : public window_creator
{
handle create_window(size_t width, size_t height, bool fullscreen) override {
//calls createWindow_ and returns WindowRef
}
};
And 2 implementations for render_system interface:
struct dx_render_system : public render_system
{
void create(handle window_handle) override{
//calls CreateDevice, etc...
}
};
struct opengl_render_system : public render_system
{
void create(handle window_handle) override{
//calls gl... etc...
}
};
Now on windows platform I can create dx or OpenGL renderer. And on MacOs I can create OpenGL renderer.
The question is: what type of handle should I create to support independence of window_creator and render_system interfaces?
In my current implementation I wrote typedef for handle:
typedef void* handle;
Is there any more elegant solution to this problem?

Generally this sort of thing is done with the following pattern:
#ifdef OS_IS_WINDOWS
#include "WindowsHandle.h"
typedef WindowsHandle NativeHandle;
#elif OS_IS_MAC
#include "MacHandle.h"
typedef MacHandle NativeHandle;
#elif OS_IS_FOO
#include "FooHandle.h"
typedef FooHandle NativeHandle;
#end
You do not need to do runtime dispatching of the different NativeHandles - and in fact without sacrificing type-safety it is nearly impossible to do - as the definition of the platform-specific handles is not available on every platform.
You already know statically at compile-time what operating system you are on, so you may as well take advantage of that.

You shouldn’t use handles at all. Handles (in this context) are a trick employed by non-OO languages to support classes.
But C++ supports classes. So use them.
class window {
// …
virtual ~window() = 0;
};
class windows_window : window { … };
class cocoa_window : window { … };
These classes are RAII objects managing the raw handle resources, and providing convenience interfaces to the appropriate windowing functions.

Related

How to avoid downcasting in this specific class hierarchy design?

I've got an assignment to create a sort of a multi-platform C++ GUI library. It wraps different GUI frameworks on different platforms. The library itself provides an interface via which the user communicates uniformly regardless of the platform he's using.
I need to design this interface and underlying communication with the framework properly. What I've tried is:
Pimpl idiom - this solution was chosen at first because of its advantages - binary compatibility, cutting the dependency tree to increase build times...
class Base {
public:
virtual void show();
// other common methods
private:
class impl;
impl* pimpl_;
};
#ifdef Framework_A
class Base::impl : public FrameWorkABase{ /* underlying platform A code */ };
#elif Framework_B
class Base::impl : public FrameWorkBBase { /* underlying platform B code */ };
#endif
class Button : public Base {
public:
void click();
private:
class impl;
impl* pimpl_;
};
#ifdef Framework_A
class Button::impl : public FrameWorkAButton{ /* underlying platform A code */ };
#elif Framework_B
class Button::impl : public FrameWorkBButton { /* underlying platform B code */ };
#endif
However, to my understanding, this pattern wasn't designed for such a complicated hierarchy where you can easily extend both interface object and its implementation. E.g. if the user wanted to subclass button from the library UserButton : Button, he would need to know the specifics of the pimpl idiom pattern to properly initialize the implementation.
Simple implementation pointer - the user doesn't need to know the underlying design of the library - if he wants to create a custom control, he simply subclasses library control and the rest is taken care of by the library
#ifdef Framework_A
using implptr = FrameWorkABase;
#elif Framework_B
using implptr = FrameWorkBBase;
#endif
class Base {
public:
void show();
protected:
implptr* pimpl_;
};
class Button : public Base {
public:
void click() {
#ifdef Framework_A
pimpl_->clickA(); // not working, need to downcast
#elif Framework_B
// works, but it's a sign of a bad design
(static_cast<FrameWorkBButton>(pimpl_))->clickB();
#endif
}
};
Since the implementation is protected, the same implptr object will be used in Button - this is possible because both FrameWorkAButton and FrameWorkBButton inherit from FrameWorkABBase and FrameWorkABase respectively. The problem with this solution is that every time i need to call e.g. in Button class something like pimpl_->click(), I need to downcast the pimpl_, because clickA() method is not in FrameWorkABase but in FrameWorkAButton, so it would look like this (static_cast<FrameWorkAButton>(pimpl_))->click(). And excessive downcasting is a sign of bad design. Visitor pattern is unacceptable in this case since there would need to be a visit method for all the methods supported by the Button class and a whole bunch of other classes.
Can somebody please tell me, how to modify these solutions or maybe suggest some other, that would make more sense in this context? Thanks in advance.
EDIT based od #ruakh 's answer
So the pimpl solution would look like this:
class baseimpl; // forward declaration (can create this in some factory)
class Base {
public:
Base(baseimpl* bi) : pimpl_ { bi } {}
virtual void show();
// other common methods
private:
baseimpl* pimpl_;
};
#ifdef Framework_A
class baseimpl : public FrameWorkABase{ /* underlying platform A code */ };
#elif Framework_B
class baseimpl : public FrameWorkBBase { /* underlying platform B code */ };
#endif
class buttonimpl; // forward declaration (can create this in some factory)
class Button : public Base {
public:
Button(buttonimpl* bi) : Base(bi), // this won't work
pimpl_ { bi } {}
void click();
private:
buttonimpl* pimpl_;
};
#ifdef Framework_A
class Button::impl : public FrameWorkAButton{ /* underlying platform A code */ };
#elif Framework_B
class Button::impl : public FrameWorkBButton { /* underlying platform B code */ };
#endif
The problem with this is that calling Base(bi) inside the Button's ctor will not work, since buttonimpl does not inherit baseimpl, only it's subclass FrameWorkABase.
The problem with this solution is that every time i need to call e.g. in Button class something like pimpl_->click(), I need to downcast the pimpl_, because clickA() method is not in FrameWorkABase but in FrameWorkAButton, so it would look like this (static_cast<FrameWorkAButton>(pimpl_))->click().
I can think of three ways to solve that issue:
Eliminate Base::pimpl_ in favor of a pure virtual protected function Base::pimpl_(). Have subclasses implement that function to provide the implementation pointer to Base::show (and any other base-class functions that need it).
Make Base::pimpl_ private rather than protected, and give subclasses their own appropriately-typed copy of the implementation pointer. (Since subclasses are responsible for calling the base-class constructor, they can ensure that they give it the same implementation pointer as they plan to use.)
Make Base::show be a pure virtual function (and likewise any other base-class functions), and implement it in subclasses. If this results in code duplication, create a separate helper function that subclasses can use.
I think that #3 is the best approach, because it avoids coupling your class hierarchy to the class hierarchies of the underlying frameworks; but I suspect from your comments above that you'll disagree. That's fine.
E.g. if the user wanted to subclass button from the library UserButton : Button, he would need to know the specifics of the pimpl idiom pattern to properly initialize the implementation.
Regardless of your approach, if you don't want the client code to have to set up the implementation pointer (since that means interacting with the underlying framework), then you will need to provide constructors or factory methods that do so. Since you want to support inheritance by client code, that means providing constructors that handle this. So I think you wrote off the Pimpl idiom too quickly.
In regards to your edit — rather than having Base::impl and Button::impl extend FrameworkABase and FrameworkAButton, you should make the FrameworkAButton be a data member of Button::impl, and give Base::impl just a pointer to it. (Or you can give Button::impl a std::unique_ptr to the FrameworkAButton instead of holding it directly; that makes it a bit easier to pass the pointer to Base::impl in a well-defined way.)
For example:
#include <memory>
//////////////////// HEADER ////////////////////
class Base {
public:
virtual ~Base() { }
protected:
class impl;
Base(std::unique_ptr<impl> &&);
private:
std::unique_ptr<impl> const pImpl;
};
class Button : public Base {
public:
Button(int);
virtual ~Button() { }
class impl;
private:
std::unique_ptr<impl> pImpl;
Button(std::unique_ptr<impl> &&);
};
/////////////////// FRAMEWORK //////////////////
class FrameworkABase {
public:
virtual ~FrameworkABase() { }
};
class FrameworkAButton : public FrameworkABase {
public:
FrameworkAButton(int) {
// just a dummy constructor, to show how Button's constructor gets wired
// up to this one
}
};
///////////////////// IMPL /////////////////////
class Base::impl {
public:
// non-owning pointer, because a subclass impl (e.g. Button::impl) holds an
// owning pointer:
FrameworkABase * const pFrameworkImpl;
impl(FrameworkABase * const pFrameworkImpl)
: pFrameworkImpl(pFrameworkImpl) { }
};
Base::Base(std::unique_ptr<Base::impl> && pImpl)
: pImpl(std::move(pImpl)) { }
class Button::impl {
public:
std::unique_ptr<FrameworkAButton> const pFrameworkImpl;
impl(std::unique_ptr<FrameworkAButton> && pFrameworkImpl)
: pFrameworkImpl(std::move(pFrameworkImpl)) { }
};
static std::unique_ptr<FrameworkAButton> makeFrameworkAButton(int const arg) {
return std::make_unique<FrameworkAButton>(arg);
}
Button::Button(std::unique_ptr<Button::impl> && pImpl)
: Base(std::make_unique<Base::impl>(pImpl->pFrameworkImpl.get())),
pImpl(std::move(pImpl)) { }
Button::Button(int const arg)
: Button(std::make_unique<Button::impl>(makeFrameworkAButton(arg))) { }
///////////////////// MAIN /////////////////////
int main() {
Button myButton(3);
return 0;
}

Is there a better solution than dynamic_cast in that case?

I'm trying to make platform independent code so I'm using OOP. For example, on Windows, Mac OS X, and Linux you can have windows, but on android you have views so I'm trying to abstract this.
I first made a class to represent a window or a view which I called view:
class View
{
public:
virtual ~View()
{}
virtual void display() = 0;
virtual void hide() = 0;
};
Now the problem is that on Android, there is no title for views while on Windows there are so I decided to create another class:
class NameableView : public View
{
public:
virtual void setName(const std::string& name)
};
And then finally implement the classes:
class WindowsView : public NameableView
{
/* Windows implementation */
}
class AndroidView : public View
{
/* Android implementation */
}
Then I need to make some code which sets the name for a view only if it is possible (if it inherits from the NameableView class).
So how can I solve this problem? I first thought about dynamic_cast but I often hear that having too much dynamic_cast is an indication of a design problem. I'm a beginner in C++ so maybe I didn't think the right way and I should change the whole design.
I'm trying to make platform independent code so I'm using OOP.
This is not an optimal approach - polymorphic hierarchies and virtual functions allow different concrete object types that inherit from the same interface to behave differently at run-time, but you know the platform you're going to target at compile-time.
What you should instead do is use static polymorphism and CRTP to provide a common interface that every concrete per-platform implementation must satisfy.
template <typename TDerived>
struct View
{
void display() { static_cast<TDerived&>(*this).display(); }
void hide() { static_cast<TDerived&>(*this).hide(); }
constexpr bool supportsSetView() const
{
return static_cast<TDerived&>(*this).supportsSetView();
}
};
In the case of setName, you should provide a supportsSetView check on every platform that returns true at compile-time if the view can be named. Then you perform that check on the caller side and only invoke setName if the check passes.
Example usage:
#if defined(PLATFORM_ANDROID)
struct AndroidView
{
// ...
constexpr bool supportsSetView() const { return false; }
};
using MyView = View<AndroidView>;
#else if defined(PLATFORM_WINDOWS)
struct WindowsView
{
// ...
constexpr bool supportsSetView() const { return true; }
void setName(std::string x) { /* ... */ }
};
using MyView = View<WindowsView>;
#else
#error "Unsupported platform."
#endif
Caller side:
MyView currentView;
if constexpr(currentView.supportsSetView())
{
currentView.setName("something");
}
As if constexpr(...)'s evaluation occurs at compile-time, the code will only call setName if it is supported by MyView.

How to pass class with virtual methods around and how to use it as member variable?

I've recently started unit testing my code, using Catch and Fakeit.
I have a wrapper class around the WinAPIs HWND.
class Window
{
public:
Window(HWND hwnd);
virtual void resize(int width, int height);
...
private:
HWND m_hwnd;
};
This and the tests for it work fine. For the tests I'm creating some actual
windows using WinAPI's CreateWindow(...).
However, I've stumbled upon a problem and I'm not sure what's the best solution to it.
In my code I just kept passing Window by value, since it's basically just the HWND anyway.
Some methods take it as const&, but when using it as class members, I usually just copied it.
class Foo
{
public:
Foo(const Window& window)
: m_window(window)
{}
private:
Window m_window;
};
Now lets assume I want to test Foo. I need to somehow stub the Window class, but I can only do that
if I am able to override virtual methods. I think you see the problem here.
class Foo
{
public:
Foo(const std::shared_ptr<Window>& window)
: m_window(window)
{
assert(m_window != nullptr);
}
private:
std::shared_ptr<Window> m_window;
};
I now spent the last two hours, refactoring all my code, so that I only pass std::shared_ptr and almost
never use the Window class by value. Foo now looks like this:
class
This makes sense, cause even if I pass the Window by value, it usually IS shared
anyway (if I resize it, it's resized for all instances).
However, I also felt that it complicated my code ALOT. For the comparison operator== I now always have to derefence
both sides. When I'm trying to find in an stl container, I now have to use
std::find_if(haystack.begin(), haystack.end(),[&needle](const SharedWindowPtr& ptr) { return *ptr == *needle; });
In addition to that, there's overhead from the shared_ptr. I also run the risk of passing nullptrs, where I want to ensure that doesn't happen. I can check that with assertions, but that isn't foolproof. I could also not pass a shared_ptr but a reference to Foo's constructor and give the Window class a std::unique_ptr<Window> clone() method, but I would have to mock that for every test and if there's a way around it I'd prefer that.
Now I'm wondering if there's any better/cleaner method for handling this kind of problem? Thanks for any advice on this.
EDIT: After thinking about this for a while, I had another idea to approach this.
class WindowHandler
{
public:
virtual void resize(int w, int h) = 0;
virtual void getTitle() = 0;
// ...
};
class DefaultWindowHandler
{
public:
DefaultWindowHandler(HWND hwnd);
virtual void resize(int w, int h) override
{
// ...
}
// ...
protected:
HWND m_hwnd;
};
class Window
{
public:
Window(HWND hwnd)
: m_windowHandler(new DefaultWindowHandler(hwnd))
{
// empty
}
void setWindowHandler(WindowHandler* handler)
{
assert(handler != nullptr);
m_windowHandler.reset(handler);
}
void resize(int w, int h)
{
m_windowHandler->resize(w, h);
}
};
What I like about this, is that I can pass the Window class around by value and still get the benefits of the interface-like behaviour if I need to. What do you think about that, what are the shortcomings? I know that the Window should probably accept a WindowHandler instead of the HWND as the constructor argument, but it's just easier to use the way it is.
Following what as been asked in the comment, it seems like std::unique_ptr will suffer from this option too. If taking by value of the base class, using any pointer or reference is not available, you can always use templates:
template<typename WindowType>
struct Foo {
// Want speed? take by value!
Foo(WindowType window)
: m_window(std::move(window))
{}
private:
WindowType m_window;
};
Then, your class will work with all subtypes of window. But then, using template, the functions being virtual or not is irrelevant.
If you want to limit your class Foo to only accept subtypes of windows, you have two choices: sfinae-like or static_assert
sfinae-like
template<typename, typename = void>
struct Foo;
template<typename WindowType>
struct Foo<WindowType, std::enable_if_t<std::is_base_of<Window, WindowType>::value>> {
Foo(WindowType window)
: m_window(std::move(window))
{}
private:
WindowType m_window;
};
static_assert
template<typename WindowType>
struct Foo {
static_assert(std::is_base_of<Window, WindowType>::value, "WindowType must be a subclass of Window");
Foo(WindowType window)
: m_window(std::move(window))
{}
private:
WindowType m_window;
};
The sfinae-like method will have the advantage of being able to "overload" your class for other types that matches with other conditions, but the static_assert is slightly easier to implement.

Designing a Window class

I'm planning out a design for my Window class. The goal is to provide an abstraction for creating a platform agnostic window ready for OpenGL rendering. I'm thinking of having a class 'Window' be the public interface, and a 'WindowImpl' class handle the work. Would making Window a friend of WindowImpl and calling WindowImpl functions inside Window cause issues? Technically, WindowImpl wouldn't be instantiated correct? So the destructor wouldn't be called which means the Window destructor wouldn't be called so a destroy function would be needed. Ex.
class MyWindow
{
public:
void create(width, height, title)
{
WindowImpl::create(width, height, title);
open = true;
}
void close()
{
WindowImpl::destroy();
open = false;
}
bool isOpen()
{
return open;
}
private:
bool open;
};
class WindowImpl
{
friend class MyWindow;
private:
static void create(width, height, title) {} // Creates the window
static void destroy()
{
XCloseDisplay(display);
}
static Display* display;
static Window window;
static GLXContext context;
};
I don't know if I'm going in the right way with this, or if I'm making things more complicated then they need to be. Since a different WindowImpl will be compiled depending on the target platform, I want to keep as much of it away from the user as possible, keeping all data like the window title and resolution inside of the Window class and any changes that are necessary can be made without the WindowImpl keeping track of anything more then the implementation specific stuff.
If it really has to be platform-agnostic, then my suggestion is to use something like this:
class WindowImpl
{
public:
virtual void setOwner(Window* pOwner) = 0
virtual void create(width, height, title) = 0;
virtual void close() = 0;
};
class Window
{
public:
void create(width, height, title)
{
mImpl->create(width, height, title);
open = true;
}
void close()
{
open = false;
mImpl->destroy();
}
Window(std::unique_ptr<WindowImpl> pImpl)
: mImpl(pImpl)
{
}
private:
std::unique_ptr<WindowImpl> mImpl;
};
// Then off somewhere else...
class WindowImplX11 : public WindowImpl
{
public:
void setOwner(Window* pOwner) {
mOwner = pOwner;
}
void destroy() {
XCloseDisplay(display);
}
private:
// Pointer back to the owner just in case (e.g. event
// delivery); if weak_ptr worked with unique_ptr, that
// would be better.
Window* mOwner;
Display* display;
GLXContext context;
};
This is a light version of the Bridge pattern, which is commonly used when you have two incompatible object hierarchies which you need to link together. This is a degenerate case (since the "hierarchy" has only one class in it), but it's still a useful technique to think about. Probably the most famous example of this is Java AWT (however AWT calls it "Peer" rather than "Impl").
Exactly how you split the responsibilities between the front end and back end is, of course, something that you need to decide for yourself, and there will probably be some back-and-forth. You may, for example, decide that an OpenGL context is a sufficiently important concept that you need to expose it to clients. The same goes for things like vsync fences which aren't fully supported in the standard way yet. Yes, I'm looking at you, OS X.
The only catch is how you construct a Window and its Impl. The traditional way is to use an abstract factory:
class Toolkit
{
public:
std::unique_ptr<Window> createWindow() = 0;
};
// then elsewhere...
// Should have been in the library, only left out by oversight.
template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}
class ToolkitX11 : public Toolkit
{
public:
std::unique_ptr<Window>
createWindow() {
return make_unique<Window>(make_unique<WindowImplX11>());
}
};
There are other ways which are a little more Modern.

Is there a better way than friend classes here?

Programming in C++ for Windows although this situation could arise anywhere. This is a simplified version of my problem to keep the question manageable so don't get too caught up on the detail :)
I have a class class Window which contains a windows HWND data item. I want to fully encapsulate that HWND so that the user of the class has to go through the class to perform any operations on that window, so it's stored in a private member variable. I don't want to provide any public "getter" for it as that would break the encapsulation allowing the user to bypass my class.
Now I want to create a class class Direct3d11 to encapsulate some of the directx api. In order to create an instance of this class it requires the HWND of a window so I pass it a Window object in it's constructor.
class Direct3D11
{
public:
Direct3D11(const Window& window);
};
Inside the constructor it has access to the window object, however it requires the HWND contained within in order to be able to physically create the windows objects that the Direct3D11 class will manage, but there is no way for it to obtain that information.
I could add a private getter function to get the HWND to the Window class, and then make the Direct3D11 class a friend class of Window so that it call call the function.
However this doesn't seem very elegant not least because class Window has otherwise no need to know anything at all about class Direct3D11.
Am I missing a better way to achieve this? Friend classes don't appeal, and having a public getter function doesn't much appeal either.
You could create the Direct3D11 class inside Window, since Windows owns the HWND.
Something along these lines:
class Window
{
HWND hwnd;
Direct3D11 d;
public:
Window() : d(hwnd) {}
Direct3D11& getDirect3D()
{
return d;
}
}
In your case I suggest to provide a getter for the HWND because you will probably be needing that more often. Providing the getter does not mean that you take the responsibility of your Window class, it is still responsible for the window's life cycle. You just make it more usable and easier to divide your code in use cases.
That said, here is a more generic approach that you could try:
class Window;
class Direct3D {
public:
void apply(Window &window, HWND hWnd);
};
class Window {
public:
void accept(Direct3D &direct3d) {
direct3d.apply(*this, this->m_hWnd);
}
};
You could maybe have a function on Window called Execute. It would take in a std::function with a placeholder for HWND as a parameter. Window would then call the function with HWND as its only parameter.
This would require c++11, but the code would be similar to :
#include <functional>
#include <iostream>
struct Foo {
explicit Foo(int num) : num_(num) {}
template<typename T>
void execute(std::function<T> f) const { f(num_); }
private:
int num_;
};
struct Bar{
void print_nums(int i,int j)
{
std::cout << "i:" << i << ", " << "j:" << j << std::endl;
}
};
int main()
{
Foo o(42);
Bar b;
//the function we want to execute requires an int
//that Foo knows about
typedef void myFunction(int);
// store the result of a call to std::bind
std::function<myFunction> display_1337_first = std::bind(&Bar::print_nums, b,1337, std::placeholders::_1);
std::function<myFunction> display_1337_last = std::bind(&Bar::print_nums, b, std::placeholders::_1, 1337);
o.execute<myFunction>(display_1337_first);
o.execute<myFunction>(display_1337_last);
return 0;
}
//output:
//i:1337, j:42
//i:42, j:1337
If you are willing to use the friend keyword you can make sure window has no knowledge of the class that needs the hwnd. Just make classes (that window and DirectX inherit from) that handle the actions for you. This allows you to solve the problem for DirectX, AND for the next time it comes around.
Side Rant:
Friend is not a four-letter word. Friend, if used reasonably, is actually a great way to add gradation to C++'s access control (public, friend (when in protected), protected, friend (when in private) , private).
#include <iostream>
class HwndOwner;
class HwndWanter
{
protected:
HwndWanter(){}
int getHwndFromOwner(HwndOwner & owner);
};
class HwndOwner
{
protected:
HwndOwner() : hwnd(42){}
private:
friend class HwndWanter;
int getHwnd()
{
return hwnd;
}
int hwnd;
};
class Window : public HwndOwner
{
//This is not the class you are looking for...
};
class Direct3D : private HwndWanter
{
public:
Direct3D(HwndOwner & owner)
: HwndWanter()
{
std::cout << getHwndFromOwner(owner) << std::endl;
}
};
int HwndWanter::getHwndFromOwner(HwndOwner & owner)
{
return owner.getHwnd();
}
int main()
{
Window window;
Direct3D hwndWanter(window);
}
Output:
42