Don't depend on global constructors for commands

This breaks when using ObjC, as these can run before the ObjC module is
initialized, resulting in non-working message sends as the selectors are
not registered yet.

FossilOrigin-Name: 1ee33c99835abc029ac202afad1f9b3bf26028e55ea1c53c53416c7566ef749d
This commit is contained in:
Jonathan Schleifer 2024-08-03 14:50:31 +00:00
parent 2fc4599331
commit 0bbe1c8bee
5 changed files with 73 additions and 8 deletions

View file

@ -2,7 +2,10 @@ project('Cube', ['c', 'objcpp'],
meson_version: '1.5.0') meson_version: '1.5.0')
add_global_arguments( add_global_arguments(
['-fobjc-arc', '-fobjc-arc-exceptions'], [
'-fobjc-arc',
'-fobjc-arc-exceptions'
],
language: 'objcpp') language: 'objcpp')
objfw_dep = dependency('objfw') objfw_dep = dependency('objfw')
@ -39,6 +42,7 @@ executable('client',
'src/console.mm', 'src/console.mm',
'src/editing.mm', 'src/editing.mm',
'src/entities.mm', 'src/entities.mm',
'src/init.mm',
'src/main.mm', 'src/main.mm',
'src/menus.mm', 'src/menus.mm',
'src/monster.mm', 'src/monster.mm',

View file

@ -1,5 +1,7 @@
// one big bad include file for the whole engine... nasty! // one big bad include file for the whole engine... nasty!
#import <ObjFW/ObjFW.h>
#include "tools.h" #include "tools.h"
enum // block types, order matters! enum // block types, order matters!
@ -390,21 +392,50 @@ enum // function signatures for script functions, see command.cpp
// nasty macros for registering script functions, abuses globals to avoid // nasty macros for registering script functions, abuses globals to avoid
// excessive infrastructure // excessive infrastructure
#define COMMANDN(name, fun, nargs) \ #define COMMANDN(name, fun, nargs) \
static bool __dummy_##fun = addcommand(#name, (void (*)())fun, nargs) OF_CONSTRUCTOR() \
{ \
enqueueInit(#name, ^{ \
addcommand(#name, (void (*)())fun, nargs); \
}); \
}
#define COMMAND(name, nargs) COMMANDN(name, name, nargs) #define COMMAND(name, nargs) COMMANDN(name, name, nargs)
#define VARP(name, min, cur, max) \ #define VARP(name, min, cur, max) \
int name = variable(#name, min, cur, max, &name, NULL, true) int name; \
OF_CONSTRUCTOR() \
{ \
enqueueInit(#name, ^{ \
name = variable(#name, min, cur, max, &name, NULL, true); \
}); \
}
#define VAR(name, min, cur, max) \ #define VAR(name, min, cur, max) \
int name = variable(#name, min, cur, max, &name, NULL, false) int name; \
OF_CONSTRUCTOR() \
{ \
enqueueInit(#name, ^{ \
name = variable(#name, min, cur, max, &name, NULL, false); \
}); \
}
#define VARF(name, min, cur, max, body) \ #define VARF(name, min, cur, max, body) \
void var_##name(); \ void var_##name(); \
static int name = \ static int name; \
variable(#name, min, cur, max, &name, var_##name, false); \ OF_CONSTRUCTOR() \
{ \
enqueueInit(#name, ^{ \
name = variable( \
#name, min, cur, max, &name, var_##name, false); \
}); \
} \
void var_##name() { body; } void var_##name() { body; }
#define VARFP(name, min, cur, max, body) \ #define VARFP(name, min, cur, max, body) \
void var_##name(); \ void var_##name(); \
static int name = \ static int name; \
variable(#name, min, cur, max, &name, var_##name, true); \ OF_CONSTRUCTOR() \
{ \
enqueueInit(#name, ^{ \
name = \
variable(#name, min, cur, max, &name, var_##name, true); \
}); \
} \
void var_##name() { body; } void var_##name() { body; }
#define ATOI(s) strtol(s, NULL, 0) // supports hexadecimal numbers #define ATOI(s) strtol(s, NULL, 0) // supports hexadecimal numbers

24
src/init.mm Normal file
View file

@ -0,0 +1,24 @@
#include <vector>
#import "cube.h"
#import "protos.h"
static std::vector<void (^)(void)> *queue;
void
enqueueInit(const char *name, void (^init)(void))
{
if (queue == NULL)
queue = new std::vector<void (^)(void)>();
queue->push_back(init);
}
void
processInitQueue(void)
{
for (auto &init : *queue)
init();
queue->clear();
}

View file

@ -104,6 +104,8 @@ main(int argc, char **argv)
char *sdesc = "", *ip = "", *master = NULL, *passwd = ""; char *sdesc = "", *ip = "", *master = NULL, *passwd = "";
islittleendian = *((char *)&islittleendian); islittleendian = *((char *)&islittleendian);
processInitQueue();
#define log(s) conoutf("init: %s", s) #define log(s) conoutf("init: %s", s)
log("sdl"); log("sdl");

View file

@ -23,6 +23,10 @@ extern void conoutf(const char *s, ...);
extern char *getcurcommand(); extern char *getcurcommand();
extern void writebinds(FILE *f); extern void writebinds(FILE *f);
// init
extern void enqueueInit(const char *name, void (^init)(void));
extern void processInitQueue(void);
// menus // menus
extern bool rendermenu(); extern bool rendermenu();
extern void menuset(int menu); extern void menuset(int menu);