typedef struct
{
WindowData data;
bool vsync;
} Window;
typedef struct
{
Window window;
GLFWwindow *native_window;
} WindowsWindow;
Window *windowCreate(const WindowProperties props, Handle id)
{
WindowsWindow *windows_window = malloc(sizeof(WindowsWindow));
*windows_window = windowswindowCreate(props);
glfwSetWindowUserPointer(windows_window->native_window, &windows_window->window.data);
Window *window = (Window *)windows_window;
window->data.id = id;
return window;
}
void windowSetContextCurrent(Window *window)
{
//log_info("Window Context current, %s", window->data.props.name);
glfwMakeContextCurrent(((WindowsWindow *)window)->native_window);
}
So This is a little snippet that hopefully conveys what I was doing before. I was casting the platform-specific window to the generic window pointer then would convert the generic pointer when needed to the platform-specific one to access its platform-specific data (just the native window currently) and I have run into the issue now of my alignment being off now specifically in my Nuklear GUI layer causing an error when deleting the window the ID of the window accesses the width of the window now instead of the windows ID (its index in my array of all windows) so I access the index at 800 instead of 0.
So lesson learned don't have a pointer point to a pointer of a different type (maybe some good use cases but definitely not here). Is there a better method to do this?
typedef struct
{
WindowData data;
bool vsync;
} Window;
typedef struct
{
Window window;
GLFWwindow *native_window;
} WindowsWindow;
Window *windowCreate(const WindowProperties props, Handle id)
{
WindowsWindow *windows_window = malloc(sizeof(WindowsWindow));
*windows_window = windowswindowCreate(props);
glfwSetWindowUserPointer(windows_window->native_window, &windows_window->window.data);
Window *window = (Window *)windows_window;
window->data.id = id;
return window;
}
void windowSetContextCurrent(Window *window)
{
//log_info("Window Context current, %s", window->data.props.name);
glfwMakeContextCurrent(((WindowsWindow *)window)->native_window);
}
So This is a little snippet that hopefully conveys what I was doing before. I was casting the platform-specific window to the generic window pointer then would convert the generic pointer when needed to the platform-specific one to access its platform-specific data (just the native window currently) and I have run into the issue now of my alignment being off now specifically in my Nuklear GUI layer causing an error when deleting the window the ID of the window accesses the width of the window now instead of the windows ID (its index in my array of all windows) so I access the index at 800 instead of 0.
So lesson learned don't have a pointer point to a pointer of a different type (maybe some good use cases but definitely not here). Is there a better method to do this?
Share Improve this question edited Mar 23 at 19:58 desertnaut 60.5k32 gold badges155 silver badges181 bronze badges asked Mar 23 at 19:02 AidanAidan 895 bronze badges 14 | Show 9 more comments1 Answer
Reset to default 1The canonical approach to this is to have a struct containing all the data that's common to the types, and a union inside it that has one of the OS-specific versions.
There are two main ways to let it know which version it's looking at: first is to have a type
field in the struct that other functions can look at to decide which element of the union to use. The other is to have all the functionality that's specific to one OS wrapped in a function, and then set up function pointers to the correct versions when you initialize the struct.
And you can always combine the two: function pointers for the differences that are worth having in their own function, and a type var for the rest.
Option 1: enum
enum Window_Type { WINDOWS, X11 };
typedef struct {
/* enum to tell us which element of the union to use. All functions that operate on a Window
* will check this first to see which branch to take/auxiliary function to call.
*/
enum Window_Type type;
//common data
unsigned id;
bool vsync;
//OS-specific data
union {
GLFWindow *windows;
X11Window *x11;
} win;
} Window;
Window *windowsWindowCreate(const WindowProperties props, Handle id) {
Window *win = malloc(sizeof(Window));
assert(win);
win->type = WINDOWS;
win->vsync = 1;
win->id = id;
win->win.windows = create_glf_window(props);
return win;
}
bool window_display(Window *win) {
// windows_window_display will look at the common fields and win.windows.
// unix_window_display will look at the common fields and win.x11.
return (WINDOWS == win->type) ? windows_window_display(win)
: (X11 == win->type) ? unix_window_display(win)
: 0;
}
Option 2: function pointers
typedef struct Window {
//common data
unsigned id;
bool vsync;
//Store the pointers to the OS-specific functions
bool (*windows_display)(struct Window *win);
//OS-specific data
union {
GLFWindow *windows;
X11Window *x11;
} win;
} Window;
Window *windowsWindowCreate(const WindowProperties props, Handle id) {
Window *win = malloc(sizeof(Window));
assert(win);
win->vsync = 1;
win->id = id;
win->win.windows = create_glf_window(props);
//Set the function pointers to the correct versions
win->windows_display = windows_window_display;
return win;
}
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744272375a4566164.html
Window *window = (Window *)windows_window;
. – Weather Vane Commented Mar 23 at 19:06window
in some variation of upper/lower case, single/plural/underscore etc appears so many times in every line, it's not exactly easy to read. – Weather Vane Commented Mar 23 at 19:21