Browse Source

Updated the Lua wrapper code for modules to account for cases where the module's instance is removed from memory completely and recreated during the program's lifetime.

Alex Szpakowski 11 years ago
parent
commit
014b9a46e5
45 changed files with 432 additions and 316 deletions
  1. 27 13
      src/common/Module.cpp
  2. 41 9
      src/common/Module.h
  3. 5 0
      src/modules/audio/Audio.cpp
  4. 1 3
      src/modules/audio/Audio.h
  5. 29 27
      src/modules/audio/wrap_Audio.cpp
  6. 1 0
      src/modules/event/Event.cpp
  7. 5 5
      src/modules/event/sdl/Event.cpp
  8. 9 8
      src/modules/event/sdl/wrap_Event.cpp
  9. 1 0
      src/modules/filesystem/physfs/Filesystem.cpp
  10. 44 43
      src/modules/filesystem/wrap_Filesystem.cpp
  11. 3 0
      src/modules/font/Font.h
  12. 7 6
      src/modules/font/freetype/wrap_Font.cpp
  13. 5 0
      src/modules/graphics/Graphics.cpp
  14. 1 0
      src/modules/graphics/Graphics.h
  15. 80 79
      src/modules/graphics/opengl/wrap_Graphics.cpp
  16. 1 3
      src/modules/image/Image.h
  17. 6 5
      src/modules/image/wrap_Image.cpp
  18. 1 0
      src/modules/joystick/JoystickModule.h
  19. 10 9
      src/modules/joystick/wrap_JoystickModule.cpp
  20. 5 0
      src/modules/keyboard/Keyboard.cpp
  21. 1 0
      src/modules/keyboard/Keyboard.h
  22. 7 6
      src/modules/keyboard/wrap_Keyboard.cpp
  23. 2 0
      src/modules/math/MathModule.cpp
  24. 5 0
      src/modules/mouse/Mouse.cpp
  25. 1 0
      src/modules/mouse/Mouse.h
  26. 18 17
      src/modules/mouse/wrap_Mouse.cpp
  27. 5 0
      src/modules/physics/box2d/Physics.cpp
  28. 2 0
      src/modules/physics/box2d/Physics.h
  29. 26 24
      src/modules/physics/box2d/wrap_Physics.cpp
  30. 5 0
      src/modules/sound/Sound.cpp
  31. 1 3
      src/modules/sound/Sound.h
  32. 6 5
      src/modules/sound/wrap_Sound.cpp
  33. 5 0
      src/modules/system/System.cpp
  34. 1 0
      src/modules/system/System.h
  35. 8 7
      src/modules/system/wrap_System.cpp
  36. 1 1
      src/modules/thread/LuaThread.cpp
  37. 5 0
      src/modules/thread/ThreadModule.cpp
  38. 1 0
      src/modules/thread/ThreadModule.h
  39. 6 5
      src/modules/thread/wrap_ThreadModule.cpp
  40. 1 3
      src/modules/timer/Timer.h
  41. 9 8
      src/modules/timer/wrap_Timer.cpp
  42. 5 0
      src/modules/window/Window.cpp
  43. 1 0
      src/modules/window/Window.h
  44. 2 2
      src/modules/window/sdl/Window.cpp
  45. 26 25
      src/modules/window/wrap_Window.cpp

+ 27 - 13
src/common/Module.cpp

@@ -58,6 +58,13 @@ namespace
 namespace love
 {
 
+Module *Module::instances[] = {};
+
+Module::Module()
+	: moduleType(M_INVALID)
+{
+}
+
 Module::~Module()
 {
 	ModuleRegistry &registry = registryInstance();
@@ -73,6 +80,14 @@ Module::~Module()
 	}
 
 	freeEmptyRegistry();
+
+	if (instances[moduleType] == this)
+		instances[moduleType] = nullptr;
+}
+
+Module::ModuleType Module::getModuleType() const
+{
+	return moduleType;
 }
 
 void Module::registerInstance(Module *instance)
@@ -93,7 +108,19 @@ void Module::registerInstance(Module *instance)
 		throw Exception("Module %s already registered!", instance->getName());
 	}
 
+	ModuleType moduletype = instance->getModuleType();
+	if (moduletype == M_INVALID)
+		throw love::Exception("Module %s has an invalid base module type.", instance->getName());
+
 	registry.insert(make_pair(name, instance));
+
+	if (instances[moduletype] != nullptr)
+	{
+		printf("Warning: overwriting module instance %s with new instance %s\n",
+			   instances[moduletype]->getName(), instance->getName());
+	}
+
+	instances[moduletype] = instance;
 }
 
 Module *Module::getInstance(const std::string &name)
@@ -108,17 +135,4 @@ Module *Module::getInstance(const std::string &name)
 	return it->second;
 }
 
-Module *Module::findInstance(const std::string &name)
-{
-	ModuleRegistry &registry = registryInstance();
-
-	for (auto it = registry.begin(); it != registry.end(); ++it)
-	{
-		if (it->first.find(name) == 0)
-			return it->second;
-	}
-
-	return nullptr;
-}
-
 } // love

+ 41 - 9
src/common/Module.h

@@ -34,11 +34,33 @@ class Module : public Object
 {
 public:
 
-	/**
-	 * Destructor.
-	 **/
+	enum ModuleType
+	{
+		M_INVALID = 0,
+		M_AUDIO,
+		M_EVENT,
+		M_FILESYSTEM,
+		M_FONT,
+		M_GRAPHICS,
+		M_IMAGE,
+		M_JOYSTICK,
+		M_KEYBOARD,
+		M_MATH,
+		M_MOUSE,
+		M_PHYSICS,
+		M_SOUND,
+		M_SYSTEM,
+		M_THREAD,
+		M_TIMER,
+		M_WINDOW,
+		M_MAX_ENUM
+	};
+
+	Module();
 	virtual ~Module();
 
+	ModuleType getModuleType() const;
+
 	/**
 	 * Gets the name of the module. This is used in case of errors
 	 * and other messages.
@@ -63,13 +85,23 @@ public:
 	static Module *getInstance(const std::string &name);
 
 	/**
-	 * Find the first module instance from the internal registry whose name
-	 * starts with the supplied name. May return NULL if module is not
-	 * registered or the supplied name is not part of any module name.
-	 * @param name The partial name of the module.
-	 * @return Module instance or NULL if the module is not registered.
+	 * Retrieve module instance from the internal registry using the base
+	 * module type. May return null if the module is not registered.
+	 * @param type The base type of the module.
 	 **/
-	static Module *findInstance(const std::string &name);
+	template <typename T>
+	static T *getInstance(ModuleType type)
+	{
+		return (T *) instances[type];
+	}
+
+protected:
+
+	ModuleType moduleType;
+
+private:
+
+	static Module *instances[M_MAX_ENUM];
 
 }; // Module
 

+ 5 - 0
src/modules/audio/Audio.cpp

@@ -25,6 +25,11 @@ namespace love
 namespace audio
 {
 
+Audio::Audio()
+{
+	moduleType = M_AUDIO;
+}
+
 StringMap<Audio::DistanceModel, Audio::DISTANCE_MAX_ENUM>::Entry Audio::distanceModelEntries[] =
 {
 	{"none", Audio::DISTANCE_NONE},

+ 1 - 3
src/modules/audio/Audio.h

@@ -64,9 +64,7 @@ public:
 	static bool getConstant(const char *in, DistanceModel &out);
 	static bool getConstant(DistanceModel in, const char  *&out);
 
-	/**
-	 * Destructor.
-	 **/
+	Audio();
 	virtual ~Audio() {}
 
 	virtual Source *newSource(love::sound::Decoder *decoder) = 0;

+ 29 - 27
src/modules/audio/wrap_Audio.cpp

@@ -31,11 +31,11 @@ namespace love
 namespace audio
 {
 
-static Audio *instance = 0;
+#define instance() (Module::getInstance<Audio>(Module::M_AUDIO))
 
 int w_getSourceCount(lua_State *L)
 {
-	lua_pushinteger(L, instance->getSourceCount());
+	lua_pushinteger(L, instance()->getSourceCount());
 	return 1;
 }
 
@@ -56,9 +56,9 @@ int w_newSource(lua_State *L)
 	Source *t = 0;
 
 	if (luax_istype(L, 1, SOUND_SOUND_DATA_T))
-		t = instance->newSource(luax_totype<love::sound::SoundData>(L, 1, "SoundData", SOUND_SOUND_DATA_T));
+		t = instance()->newSource(luax_totype<love::sound::SoundData>(L, 1, "SoundData", SOUND_SOUND_DATA_T));
 	else if (luax_istype(L, 1, SOUND_DECODER_T))
-		t = instance->newSource(luax_totype<love::sound::Decoder>(L, 1, "Decoder", SOUND_DECODER_T));
+		t = instance()->newSource(luax_totype<love::sound::Decoder>(L, 1, "Decoder", SOUND_DECODER_T));
 
 	if (t)
 	{
@@ -72,7 +72,7 @@ int w_newSource(lua_State *L)
 int w_play(lua_State *L)
 {
 	Source *s = luax_checksource(L, 1);
-	luax_pushboolean(L, instance->play(s));
+	luax_pushboolean(L, instance()->play(s));
 	return 1;
 }
 
@@ -80,7 +80,7 @@ int w_stop(lua_State *L)
 {
 	if (lua_gettop(L) == 0)
 	{
-		instance->stop();
+		instance()->stop();
 	}
 	else
 	{
@@ -94,7 +94,7 @@ int w_pause(lua_State *L)
 {
 	if (lua_gettop(L) == 0)
 	{
-		instance->pause();
+		instance()->pause();
 	}
 	else
 	{
@@ -109,7 +109,7 @@ int w_resume(lua_State *L)
 {
 	if (lua_gettop(L) == 0)
 	{
-		instance->resume();
+		instance()->resume();
 	}
 	else
 	{
@@ -123,7 +123,7 @@ int w_rewind(lua_State *L)
 {
 	if (lua_gettop(L) == 0)
 	{
-		instance->rewind();
+		instance()->rewind();
 	}
 	else
 	{
@@ -136,13 +136,13 @@ int w_rewind(lua_State *L)
 int w_setVolume(lua_State *L)
 {
 	float v = (float)luaL_checknumber(L, 1);
-	instance->setVolume(v);
+	instance()->setVolume(v);
 	return 0;
 }
 
 int w_getVolume(lua_State *L)
 {
-	lua_pushnumber(L, instance->getVolume());
+	lua_pushnumber(L, instance()->getVolume());
 	return 1;
 }
 
@@ -152,14 +152,14 @@ int w_setPosition(lua_State *L)
 	v[0] = (float)luaL_checknumber(L, 1);
 	v[1] = (float)luaL_checknumber(L, 2);
 	v[2] = (float)luaL_optnumber(L, 3, 0);
-	instance->setPosition(v);
+	instance()->setPosition(v);
 	return 0;
 }
 
 int w_getPosition(lua_State *L)
 {
 	float v[3];
-	instance->getPosition(v);
+	instance()->getPosition(v);
 	lua_pushnumber(L, v[0]);
 	lua_pushnumber(L, v[1]);
 	lua_pushnumber(L, v[2]);
@@ -175,14 +175,14 @@ int w_setOrientation(lua_State *L)
 	v[3] = (float)luaL_checknumber(L, 4);
 	v[4] = (float)luaL_checknumber(L, 5);
 	v[5] = (float)luaL_checknumber(L, 6);
-	instance->setOrientation(v);
+	instance()->setOrientation(v);
 	return 0;
 }
 
 int w_getOrientation(lua_State *L)
 {
 	float v[6];
-	instance->getOrientation(v);
+	instance()->getOrientation(v);
 	lua_pushnumber(L, v[0]);
 	lua_pushnumber(L, v[1]);
 	lua_pushnumber(L, v[2]);
@@ -198,14 +198,14 @@ int w_setVelocity(lua_State *L)
 	v[0] = (float)luaL_checknumber(L, 1);
 	v[1] = (float)luaL_checknumber(L, 2);
 	v[2] = (float)luaL_optnumber(L, 3, 0);
-	instance->setVelocity(v);
+	instance()->setVelocity(v);
 	return 0;
 }
 
 int w_getVelocity(lua_State *L)
 {
 	float v[3];
-	instance->getVelocity(v);
+	instance()->getVelocity(v);
 	lua_pushnumber(L, v[0]);
 	lua_pushnumber(L, v[1]);
 	lua_pushnumber(L, v[2]);
@@ -214,13 +214,13 @@ int w_getVelocity(lua_State *L)
 
 int w_record(lua_State *)
 {
-	instance->record();
+	instance()->record();
 	return 0;
 }
 
 int w_getRecordedData(lua_State *L)
 {
-	love::sound::SoundData *sd = instance->getRecordedData();
+	love::sound::SoundData *sd = instance()->getRecordedData();
 	if (!sd)
 		lua_pushnil(L);
 	else
@@ -232,18 +232,18 @@ int w_stopRecording(lua_State *L)
 {
 	if (luax_optboolean(L, 1, true))
 	{
-		love::sound::SoundData *sd = instance->stopRecording(true);
+		love::sound::SoundData *sd = instance()->stopRecording(true);
 		if (!sd) lua_pushnil(L);
 		else luax_pushtype(L, "SoundData", SOUND_SOUND_DATA_T, sd);
 		return 1;
 	}
-	instance->stopRecording(false);
+	instance()->stopRecording(false);
 	return 0;
 }
 
 int w_canRecord(lua_State *L)
 {
-	luax_pushboolean(L, instance->canRecord());
+	luax_pushboolean(L, instance()->canRecord());
 	return 1;
 }
 
@@ -253,13 +253,13 @@ int w_setDistanceModel(lua_State *L)
 	Audio::DistanceModel distanceModel;
 	if (!Audio::getConstant(modelStr, distanceModel))
 		return luaL_error(L, "Invalid distance model: %s", modelStr);
-	instance->setDistanceModel(distanceModel);
+	instance()->setDistanceModel(distanceModel);
 	return 0;
 }
 
 int w_getDistanceModel(lua_State *L)
 {
-	Audio::DistanceModel distanceModel = instance->getDistanceModel();
+	Audio::DistanceModel distanceModel = instance()->getDistanceModel();
 	const char *modelStr;
 	if (!Audio::getConstant(distanceModel, modelStr))
 		return 0;
@@ -301,8 +301,10 @@ static const lua_CFunction types[] =
 
 extern "C" int luaopen_love_audio(lua_State *L)
 {
+	Audio *instance = instance();
+
 #ifdef LOVE_ENABLE_AUDIO_OPENAL
-	if (instance == 0)
+	if (instance == nullptr)
 	{
 		// Try OpenAL first.
 		try
@@ -319,7 +321,7 @@ extern "C" int luaopen_love_audio(lua_State *L)
 #endif
 
 #ifdef LOVE_ENABLE_AUDIO_NULL
-	if (instance == 0)
+	if (instance == nullptr)
 	{
 		// Fall back to nullaudio.
 		try
@@ -333,7 +335,7 @@ extern "C" int luaopen_love_audio(lua_State *L)
 	}
 #endif
 
-	if (instance == 0)
+	if (instance == nullptr)
 		return luaL_error(L, "Could not open any audio module.");
 
 	WrappedModule w;

+ 1 - 0
src/modules/event/Event.cpp

@@ -82,6 +82,7 @@ Message *Message::fromLua(lua_State *L, int n)
 
 Event::Event()
 {
+	moduleType = M_EVENT;
 	mutex = thread::newMutex();
 }
 

+ 5 - 5
src/modules/event/sdl/Event.cpp

@@ -44,7 +44,7 @@ static void windowToPixelCoords(int *x, int *y)
 {
 	double scale = 1.0;
 
-	window::Window *window = (window::Window *) Module::findInstance("love.window.");
+	window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW);
 	if (window != nullptr)
 		scale = window->getPixelScale();
 
@@ -129,7 +129,7 @@ Message *Event::convert(const SDL_Event &e) const
 	case SDL_KEYDOWN:
 		if (e.key.repeat)
 		{
-			kb = (love::keyboard::Keyboard *) Module::findInstance("love.keyboard.");
+			kb = Module::getInstance<love::keyboard::Keyboard>(Module::M_KEYBOARD);
 			if (kb && !kb->hasKeyRepeat())
 				break;
 		}
@@ -245,7 +245,7 @@ Message *Event::convert(const SDL_Event &e) const
 
 Message *Event::convertJoystickEvent(const SDL_Event &e) const
 {
-	joystick::JoystickModule *joymodule = (joystick::JoystickModule *) Module::findInstance("love.joystick.");
+	joystick::JoystickModule *joymodule = Module::getInstance<joystick::JoystickModule>(Module::M_JOYSTICK);
 	if (!joymodule)
 		return 0;
 
@@ -416,7 +416,7 @@ Message *Event::convertWindowEvent(const SDL_Event &e) const
 		arg1->release();
 		break;
 	case SDL_WINDOWEVENT_RESIZED:
-		win = (window::Window *) Module::findInstance("love.window.");
+		win = Module::getInstance<window::Window>(Module::M_WINDOW);
 		if (win)
 		{
 			int px_w = e.window.data1;
@@ -431,7 +431,7 @@ Message *Event::convertWindowEvent(const SDL_Event &e) const
 
 			win->onWindowResize(e.window.data1, e.window.data2);
 
-			graphics::Graphics *gfx = (graphics::Graphics *) Module::findInstance("love.graphics.");
+			graphics::Graphics *gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
 			if (gfx)
 				gfx->setViewportSize(px_w, px_h);
 

+ 9 - 8
src/modules/event/sdl/wrap_Event.cpp

@@ -33,13 +33,13 @@ namespace event
 namespace sdl
 {
 
-static Event *instance = 0;
+#define instance() (Module::getInstance<Event>(Module::M_EVENT))
 
 static int poll_i(lua_State *L)
 {
 	Message *m;
 
-	while (instance->poll(m))
+	while (instance()->poll(m))
 	{
 		int args = m->toLua(L);
 		m->release();
@@ -52,7 +52,7 @@ static int poll_i(lua_State *L)
 
 int w_pump(lua_State *)
 {
-	instance->pump();
+	instance()->pump();
 	return 0;
 }
 
@@ -66,7 +66,7 @@ int w_wait(lua_State *L)
 {
 	Message *m;
 
-	if ((m = instance->wait()))
+	if ((m = instance()->wait()))
 	{
 		int args = m->toLua(L);
 		m->release();
@@ -86,7 +86,7 @@ int w_push(lua_State *L)
 	if (!success)
 		return 1;
 
-	instance->push(m);
+	instance()->push(m);
 	m->release();
 
 	return 1;
@@ -94,14 +94,14 @@ int w_push(lua_State *L)
 
 int w_clear(lua_State *)
 {
-	instance->clear();
+	instance()->clear();
 	return 0;
 }
 
 int w_quit(lua_State *L)
 {
 	Message *m = new Message("quit");
-	instance->push(m);
+	instance()->push(m);
 	m->release();
 	luax_pushboolean(L, true);
 	return 1;
@@ -121,7 +121,8 @@ static const luaL_Reg functions[] =
 
 extern "C" int luaopen_love_event(lua_State *L)
 {
-	if (instance == 0)
+	Event *instance = instance();
+	if (instance == nullptr)
 	{
 		luax_catchexcept(L, [&](){ instance = new Event(); });
 	}

+ 1 - 0
src/modules/filesystem/physfs/Filesystem.cpp

@@ -77,6 +77,7 @@ Filesystem::Filesystem()
 	, fused(false)
 	, fusedSet(false)
 {
+	moduleType = M_FILESYSTEM;
 }
 
 Filesystem::~Filesystem()

+ 44 - 43
src/modules/filesystem/wrap_Filesystem.cpp

@@ -32,20 +32,20 @@ namespace love
 {
 namespace filesystem
 {
-
-static physfs::Filesystem *instance = 0;
+	
+#define instance() (Module::getInstance<physfs::Filesystem>(Module::M_FILESYSTEM))
 
 bool hack_setupWriteDirectory()
 {
-	if (instance != 0)
-		return instance->setupWriteDirectory();
+	if (instance() != 0)
+		return instance()->setupWriteDirectory();
 	return false;
 }
 
 int w_init(lua_State *L)
 {
 	const char *arg0 = luaL_checkstring(L, 1);
-	luax_catchexcept(L, [&](){ instance->init(arg0); });
+	luax_catchexcept(L, [&](){ instance()->init(arg0); });
 	return 0;
 }
 
@@ -53,13 +53,13 @@ int w_setFused(lua_State *L)
 {
 	// no error checking needed, everything, even nothing
 	// can be converted to a boolean
-	instance->setFused(luax_toboolean(L, 1));
+	instance()->setFused(luax_toboolean(L, 1));
 	return 0;
 }
 
 int w_isFused(lua_State *L)
 {
-	luax_pushboolean(L, instance->isFused());
+	luax_pushboolean(L, instance()->isFused());
 	return 1;
 }
 
@@ -68,7 +68,7 @@ int w_setIdentity(lua_State *L)
 	const char *arg = luaL_checkstring(L, 1);
 	bool append = luax_optboolean(L, 2, false);
 
-	if (!instance->setIdentity(arg, append))
+	if (!instance()->setIdentity(arg, append))
 		return luaL_error(L, "Could not set write directory.");
 
 	return 0;
@@ -76,7 +76,7 @@ int w_setIdentity(lua_State *L)
 
 int w_getIdentity(lua_State *L)
 {
-	lua_pushstring(L, instance->getIdentity());
+	lua_pushstring(L, instance()->getIdentity());
 	return 1;
 }
 
@@ -84,7 +84,7 @@ int w_setSource(lua_State *L)
 {
 	const char *arg = luaL_checkstring(L, 1);
 
-	if (!instance->setSource(arg))
+	if (!instance()->setSource(arg))
 		return luaL_error(L, "Could not set source.");
 
 	return 0;
@@ -92,7 +92,7 @@ int w_setSource(lua_State *L)
 
 int w_getSource(lua_State *L)
 {
-	lua_pushstring(L, instance->getSource());
+	lua_pushstring(L, instance()->getSource());
 	return 1;
 }
 
@@ -102,7 +102,7 @@ int w_mount(lua_State *L)
 	const char *mountpoint = luaL_checkstring(L, 2);
 	bool append = luax_optboolean(L, 3, false);
 
-	luax_pushboolean(L, instance->mount(archive, mountpoint, append));
+	luax_pushboolean(L, instance()->mount(archive, mountpoint, append));
 	return 1;
 }
 
@@ -110,7 +110,7 @@ int w_unmount(lua_State *L)
 {
 	const char *archive = luaL_checkstring(L, 1);
 
-	luax_pushboolean(L, instance->unmount(archive));
+	luax_pushboolean(L, instance()->unmount(archive));
 	return 1;
 }
 
@@ -128,7 +128,7 @@ int w_newFile(lua_State *L)
 			return luaL_error(L, "Incorrect file open mode: %s", str);
 	}
 
-	File *t = instance->newFile(filename);
+	File *t = instance()->newFile(filename);
 
 	if (mode != File::CLOSED)
 	{
@@ -156,7 +156,7 @@ FileData *luax_getfiledata(lua_State *L, int idx)
 	if (lua_isstring(L, idx))
 	{
 		const char *filename = luaL_checkstring(L, idx);
-		file = instance->newFile(filename);
+		file = instance()->newFile(filename);
 	}
 	else if (luax_istype(L, idx, FILESYSTEM_FILE_T))
 	{
@@ -231,10 +231,10 @@ int w_newFileData(lua_State *L)
 	switch (decoder)
 	{
 	case FileData::FILE:
-		t = instance->newFileData((void *)str, (int)length, filename);
+		t = instance()->newFileData((void *)str, (int)length, filename);
 		break;
 	case FileData::BASE64:
-		t = instance->newFileData(str, filename);
+		t = instance()->newFileData(str, filename);
 		break;
 	default:
 		return luaL_error(L, "Invalid FileData decoder: %s", decstr);
@@ -246,66 +246,66 @@ int w_newFileData(lua_State *L)
 
 int w_getWorkingDirectory(lua_State *L)
 {
-	lua_pushstring(L, instance->getWorkingDirectory());
+	lua_pushstring(L, instance()->getWorkingDirectory());
 	return 1;
 }
 
 int w_getUserDirectory(lua_State *L)
 {
-	luax_pushstring(L, instance->getUserDirectory());
+	luax_pushstring(L, instance()->getUserDirectory());
 	return 1;
 }
 
 int w_getAppdataDirectory(lua_State *L)
 {
-	luax_pushstring(L, instance->getAppdataDirectory());
+	luax_pushstring(L, instance()->getAppdataDirectory());
 	return 1;
 }
 
 int w_getSaveDirectory(lua_State *L)
 {
-	lua_pushstring(L, instance->getSaveDirectory());
+	lua_pushstring(L, instance()->getSaveDirectory());
 	return 1;
 }
 
 int w_getSourceBaseDirectory(lua_State *L)
 {
-	luax_pushstring(L, instance->getSourceBaseDirectory());
+	luax_pushstring(L, instance()->getSourceBaseDirectory());
 	return 1;
 }
 
 int w_exists(lua_State *L)
 {
 	const char *arg = luaL_checkstring(L, 1);
-	luax_pushboolean(L, instance->exists(arg));
+	luax_pushboolean(L, instance()->exists(arg));
 	return 1;
 }
 
 int w_isDirectory(lua_State *L)
 {
 	const char *arg = luaL_checkstring(L, 1);
-	luax_pushboolean(L, instance->isDirectory(arg));
+	luax_pushboolean(L, instance()->isDirectory(arg));
 	return 1;
 }
 
 int w_isFile(lua_State *L)
 {
 	const char *arg = luaL_checkstring(L, 1);
-	luax_pushboolean(L, instance->isFile(arg));
+	luax_pushboolean(L, instance()->isFile(arg));
 	return 1;
 }
 
 int w_createDirectory(lua_State *L)
 {
 	const char *arg = luaL_checkstring(L, 1);
-	luax_pushboolean(L, instance->createDirectory(arg));
+	luax_pushboolean(L, instance()->createDirectory(arg));
 	return 1;
 }
 
 int w_remove(lua_State *L)
 {
 	const char *arg = luaL_checkstring(L, 1);
-	luax_pushboolean(L, instance->remove(arg));
+	luax_pushboolean(L, instance()->remove(arg));
 	return 1;
 }
 
@@ -317,7 +317,7 @@ int w_read(lua_State *L)
 	Data *data = 0;
 	try
 	{
-		data = instance->read(filename, len);
+		data = instance()->read(filename, len);
 	}
 	catch (love::Exception &e)
 	{
@@ -363,9 +363,9 @@ static int w_write_or_append(lua_State *L, File::Mode mode)
 	try
 	{
 		if (mode == File::APPEND)
-			instance->append(filename, (const void *) input, len);
+			instance()->append(filename, (const void *) input, len);
 		else
-			instance->write(filename, (const void *) input, len);
+			instance()->write(filename, (const void *) input, len);
 	}
 	catch (love::Exception &e)
 	{
@@ -388,7 +388,7 @@ int w_append(lua_State *L)
 
 int w_getDirectoryItems(lua_State *L)
 {
-	return instance->getDirectoryItems(L);
+	return instance()->getDirectoryItems(L);
 }
 
 int w_lines(lua_State *L)
@@ -397,7 +397,7 @@ int w_lines(lua_State *L)
 
 	if (lua_isstring(L, 1))
 	{
-		file = instance->newFile(lua_tostring(L, 1));
+		file = instance()->newFile(lua_tostring(L, 1));
 		bool success = false;
 
 		luax_catchexcept(L, [&](){ success = file->open(File::READ); });
@@ -421,7 +421,7 @@ int w_load(lua_State *L)
 	Data *data = 0;
 	try
 	{
-		data = instance->read(filename.c_str());
+		data = instance()->read(filename.c_str());
 	}
 	catch (love::Exception &e)
 	{
@@ -451,7 +451,7 @@ int w_getLastModified(lua_State *L)
 	int64 time = 0;
 	try
 	{
-		time = instance->getLastModified(filename);
+		time = instance()->getLastModified(filename);
 	}
 	catch (love::Exception &e)
 	{
@@ -469,7 +469,7 @@ int w_getSize(lua_State *L)
 	int64 size = -1;
 	try
 	{
-		size = instance->getSize(filename);
+		size = instance()->getSize(filename);
 	}
 	catch (love::Exception &e)
 	{
@@ -504,7 +504,7 @@ int loader(lua_State *L)
 	}
 
 	// Check whether file exists.
-	if (instance->exists(tmp.c_str()))
+	if (instance()->exists(tmp.c_str()))
 	{
 		lua_pop(L, 1);
 		lua_pushstring(L, tmp.c_str());
@@ -522,10 +522,10 @@ int loader(lua_State *L)
 		}
 	}
 
-	if (instance->isDirectory(tmp.c_str()))
+	if (instance()->isDirectory(tmp.c_str()))
 	{
 		tmp += "/init.lua";
-		if (instance->exists(tmp.c_str()))
+		if (instance()->exists(tmp.c_str()))
 		{
 			lua_pop(L, 1);
 			lua_pushstring(L, tmp.c_str());
@@ -570,15 +570,15 @@ int extloader(lua_State *L)
 	void *handle = nullptr;
 
 	// If the game is fused, try looking for the DLL in the game's read paths.
-	if (instance->isFused())
+	if (instance()->isFused())
 	{
 		try
 		{
-			std::string dir = instance->getRealDirectory(tokenized_name.c_str());
+			std::string dir = instance()->getRealDirectory(tokenized_name.c_str());
 
 			// We don't want to look in the game's source, because it can be a
 			// zip sometimes and a folder other times.
-			if (dir.find(instance->getSource()) == std::string::npos)
+			if (dir.find(instance()->getSource()) == std::string::npos)
 				handle = SDL_LoadObject((dir + LOVE_PATH_SEPARATOR + tokenized_name).c_str());
 		}
 		catch (love::Exception &)
@@ -589,7 +589,7 @@ int extloader(lua_State *L)
 
 	if (!handle)
 	{
-		std::string path = std::string(instance->getAppdataDirectory()) + LOVE_PATH_SEPARATOR LOVE_APPDATA_FOLDER LOVE_PATH_SEPARATOR + tokenized_name;
+		std::string path = std::string(instance()->getAppdataDirectory()) + LOVE_PATH_SEPARATOR LOVE_APPDATA_FOLDER LOVE_PATH_SEPARATOR + tokenized_name;
 		handle = SDL_LoadObject(path.c_str());
 	}
 
@@ -658,7 +658,8 @@ static const lua_CFunction types[] =
 
 extern "C" int luaopen_love_filesystem(lua_State *L)
 {
-	if (instance == 0)
+	physfs::Filesystem *instance = instance();
+	if (instance == nullptr)
 	{
 		luax_catchexcept(L, [&](){ instance = new physfs::Filesystem(); });
 	}

+ 3 - 0
src/modules/font/Font.h

@@ -40,6 +40,9 @@ class Font : public Module
 
 public:
 
+	Font() { moduleType = M_FONT; }
+	virtual ~Font() {}
+
 	virtual Rasterizer *newRasterizer(Data *data, int size) = 0;
 	virtual Rasterizer *newRasterizer(love::image::ImageData *data, const std::string &glyphs) = 0;
 	virtual Rasterizer *newRasterizer(love::image::ImageData *data, uint32 *glyphs, int length) = 0;

+ 7 - 6
src/modules/font/freetype/wrap_Font.cpp

@@ -36,7 +36,7 @@ namespace font
 namespace freetype
 {
 
-static Font *instance = nullptr;
+#define instance() (Module::getInstance<Font>(Module::M_FONT))
 
 int w_newRasterizer(lua_State *L)
 {
@@ -47,14 +47,14 @@ int w_newRasterizer(lua_State *L)
 		love::image::ImageData *d = luax_checktype<love::image::ImageData>(L, 1, "ImageData", IMAGE_IMAGE_DATA_T);
 		const char *g = luaL_checkstring(L, 2);
 		std::string glyphs(g);
-		luax_catchexcept(L, [&](){ t = instance->newRasterizer(d, glyphs); });
+		luax_catchexcept(L, [&](){ t = instance()->newRasterizer(d, glyphs); });
 	}
 	else if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_T))
 	{
 		love::filesystem::FileData *d = love::filesystem::luax_getfiledata(L, 1);
 		int size = luaL_checkint(L, 2);
 		luax_catchexcept(L,
-			[&]() { t = instance->newRasterizer(d, size); },
+			[&]() { t = instance()->newRasterizer(d, size); },
 			[&]() { d->release(); }
 		);
 	}
@@ -72,12 +72,12 @@ int w_newGlyphData(lua_State *L)
 	if (lua_type(L, 2) == LUA_TSTRING)
 	{
 		std::string glyph = luax_checkstring(L, 2);
-		luax_catchexcept(L, [&](){ t = instance->newGlyphData(r, glyph); });
+		luax_catchexcept(L, [&](){ t = instance()->newGlyphData(r, glyph); });
 	}
 	else
 	{
 		uint32 g = (uint32) luaL_checknumber(L, 2);
-		t = instance->newGlyphData(r, g);
+		t = instance()->newGlyphData(r, g);
 	}
 
 	luax_pushtype(L, "GlyphData", FONT_GLYPH_DATA_T, t);
@@ -101,9 +101,10 @@ static const lua_CFunction types[] =
 
 extern "C" int luaopen_love_font(lua_State *L)
 {
+	Font *instance = instance();
 	if (instance == nullptr)
 	{
-		luax_catchexcept(L, [](){ instance = new Font(); });
+		luax_catchexcept(L, [&](){ instance = new Font(); });
 	}
 	else
 		instance->retain();

+ 5 - 0
src/modules/graphics/Graphics.cpp

@@ -25,6 +25,11 @@ namespace love
 namespace graphics
 {
 
+Graphics::Graphics()
+{
+	moduleType = M_GRAPHICS;
+}
+
 Graphics::~Graphics()
 {
 }

+ 1 - 0
src/modules/graphics/Graphics.h

@@ -120,6 +120,7 @@ public:
 		std::string device;
 	};
 
+	Graphics();
 	virtual ~Graphics();
 
 	/**

+ 80 - 79
src/modules/graphics/opengl/wrap_Graphics.cpp

@@ -36,48 +36,48 @@ namespace graphics
 namespace opengl
 {
 
-static Graphics *instance = nullptr;
+#define instance() (Module::getInstance<Graphics>(Module::M_GRAPHICS))
 
 int w_reset(lua_State *)
 {
-	instance->reset();
+	instance()->reset();
 	return 0;
 }
 
 int w_clear(lua_State *)
 {
-	instance->clear();
+	instance()->clear();
 	return 0;
 }
 
 int w_present(lua_State *)
 {
-	instance->present();
+	instance()->present();
 	return 0;
 }
 
 int w_isCreated(lua_State *L)
 {
-	luax_pushboolean(L, instance->isCreated());
+	luax_pushboolean(L, instance()->isCreated());
 	return 1;
 }
 
 int w_getWidth(lua_State *L)
 {
-	lua_pushinteger(L, instance->getWidth());
+	lua_pushinteger(L, instance()->getWidth());
 	return 1;
 }
 
 int w_getHeight(lua_State *L)
 {
-	lua_pushinteger(L, instance->getHeight());
+	lua_pushinteger(L, instance()->getHeight());
 	return 1;
 }
 
 int w_getDimensions(lua_State *L)
 {
-	lua_pushinteger(L, instance->getWidth());
-	lua_pushinteger(L, instance->getHeight());
+	lua_pushinteger(L, instance()->getWidth());
+	lua_pushinteger(L, instance()->getHeight());
 	return 2;
 }
 
@@ -88,7 +88,7 @@ int w_setScissor(lua_State *L)
 	if (nargs == 0 || (nargs == 4 && lua_isnil(L, 1) && lua_isnil(L, 2)
 		&& lua_isnil(L, 3) && lua_isnil(L, 4)))
 	{
-		instance->setScissor();
+		instance()->setScissor();
 		return 0;
 	}
 
@@ -100,14 +100,14 @@ int w_setScissor(lua_State *L)
 	if (w < 0 || h < 0)
 		return luaL_error(L, "Can't set scissor with negative width and/or height.");
 
-	instance->setScissor(x, y, w, h);
+	instance()->setScissor(x, y, w, h);
 	return 0;
 }
 
 int w_getScissor(lua_State *L)
 {
 	int x, y, w, h;
-	if (!instance->getScissor(x, y, w, h))
+	if (!instance()->getScissor(x, y, w, h))
 		return 0;
 
 	lua_pushinteger(L, x);
@@ -123,15 +123,15 @@ static int setStencil(lua_State *L, bool invert)
 	// no argument -> clear stencil
 	if (lua_isnoneornil(L, 1))
 	{
-		instance->discardStencil();
+		instance()->discardStencil();
 		return 0;
 	}
 
 	luaL_checktype(L, 1, LUA_TFUNCTION);
 
-	instance->defineStencil();
+	instance()->defineStencil();
 	lua_call(L, lua_gettop(L) - 1, 0); // call stencil(...)
-	instance->useStencil(invert);
+	instance()->useStencil(invert);
 
 	return 0;
 }
@@ -148,7 +148,7 @@ int w_setInvertedStencil(lua_State *L)
 
 int w_getMaxTextureSize(lua_State *L)
 {
-	lua_pushinteger(L, instance->getSystemLimit(Graphics::LIMIT_TEXTURE_SIZE));
+	lua_pushinteger(L, instance()->getSystemLimit(Graphics::LIMIT_TEXTURE_SIZE));
 	return 1;
 }
 
@@ -168,7 +168,7 @@ int w_newImage(lua_State *L)
 	// Convert to ImageData / CompressedData, if necessary.
 	if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_T))
 	{
-		love::image::Image *image = (love::image::Image *) Module::findInstance("love.image.");
+		love::image::Image *image = Module::getInstance<love::image::Image>(Module::M_IMAGE);
 		if (image == nullptr)
 			return luaL_error(L, "Cannot load images without the love.image module.");
 
@@ -205,9 +205,9 @@ int w_newImage(lua_State *L)
 	luax_catchexcept(L,
 		[&]() {
 			if (cdata)
-				image = instance->newImage(cdata, format);
+				image = instance()->newImage(cdata, format);
 			else if (data)
-				image = instance->newImage(data, format);
+				image = instance()->newImage(data, format);
 		},
 		[&]() {
 			if (releasedata && data)
@@ -236,7 +236,7 @@ int w_newQuad(lua_State *L)
 	float sw = (float) luaL_checknumber(L, 5);
 	float sh = (float) luaL_checknumber(L, 6);
 
-	Quad *quad = instance->newQuad(v, sw, sh);
+	Quad *quad = instance()->newQuad(v, sw, sh);
 	luax_pushtype(L, "Quad", GRAPHICS_QUAD_T, quad);
 	return 1;
 }
@@ -254,7 +254,7 @@ int w_newFont(lua_State *L)
 
 	Font *font = 0;
 	luax_catchexcept(L, [&]() {
-		font = instance->newFont(rasterizer, instance->getDefaultFilter()); }
+		font = instance()->newFont(rasterizer, instance()->getDefaultFilter()); }
 	);
 
 	if (font == 0)
@@ -268,7 +268,7 @@ int w_newFont(lua_State *L)
 int w_newImageFont(lua_State *L)
 {
 	// filter for glyphs
-	Texture::Filter filter = instance->getDefaultFilter();
+	Texture::Filter filter = instance()->getDefaultFilter();
 
 	// Convert to ImageData if necessary.
 	if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_T))
@@ -295,7 +295,7 @@ int w_newImageFont(lua_State *L)
 	love::font::Rasterizer *rasterizer = luax_checktype<love::font::Rasterizer>(L, 1, "Rasterizer", FONT_RASTERIZER_T);
 
 	// Create the font.
-	Font *font = instance->newFont(rasterizer, filter);
+	Font *font = instance()->newFont(rasterizer, filter);
 
 	if (font == 0)
 		return luaL_error(L, "Could not load font.");
@@ -320,7 +320,7 @@ int w_newSpriteBatch(lua_State *L)
 
 	SpriteBatch *t = nullptr;
 	luax_catchexcept(L,
-		[&](){ t = instance->newSpriteBatch(texture, size, usage); }
+		[&](){ t = instance()->newSpriteBatch(texture, size, usage); }
 	);
 
 	luax_pushtype(L, "SpriteBatch", GRAPHICS_SPRITE_BATCH_T, t);
@@ -336,7 +336,7 @@ int w_newParticleSystem(lua_State *L)
 		return luaL_error(L, "Invalid ParticleSystem size");	
 
 	luax_catchexcept(L,
-		[&](){ t = instance->newParticleSystem(texture, int(size)); }
+		[&](){ t = instance()->newParticleSystem(texture, int(size)); }
 	);
 
 	luax_pushtype(L, "ParticleSystem", GRAPHICS_PARTICLE_SYSTEM_T, t);
@@ -346,8 +346,8 @@ int w_newParticleSystem(lua_State *L)
 int w_newCanvas(lua_State *L)
 {
 	// check if width and height are given. else default to screen dimensions.
-	int width       = luaL_optint(L, 1, instance->getWidth());
-	int height      = luaL_optint(L, 2, instance->getHeight());
+	int width       = luaL_optint(L, 1, instance()->getWidth());
+	int height      = luaL_optint(L, 2, instance()->getHeight());
 	const char *str = luaL_optstring(L, 3, "normal");
 	int msaa        = luaL_optint(L, 4, 0);
 
@@ -357,7 +357,7 @@ int w_newCanvas(lua_State *L)
 
 	Canvas *canvas = nullptr;
 	luax_catchexcept(L,
-		[&](){ canvas = instance->newCanvas(width, height, format, msaa); }
+		[&](){ canvas = instance()->newCanvas(width, height, format, msaa); }
 	);
 
 	if (canvas == nullptr)
@@ -448,7 +448,7 @@ int w_newShader(lua_State *L)
 	bool should_error = false;
 	try
 	{
-		Shader *shader = instance->newShader(sources);
+		Shader *shader = instance()->newShader(sources);
 		luax_pushtype(L, "Shader", GRAPHICS_SHADER_T, shader);
 	}
 	catch (love::Exception &e)
@@ -529,13 +529,13 @@ int w_newMesh(lua_State *L)
 			vertices.push_back(v);
 		}
 
-		luax_catchexcept(L, [&](){ t = instance->newMesh(vertices, mode); });
+		luax_catchexcept(L, [&](){ t = instance()->newMesh(vertices, mode); });
 		t->setVertexColors(use_colors);
 	}
 	else
 	{
 		int count = luaL_checkint(L, 1);
-		luax_catchexcept(L, [&](){ t = instance->newMesh(count, mode); });
+		luax_catchexcept(L, [&](){ t = instance()->newMesh(count, mode); });
 	}
 
 	if (tex)
@@ -567,13 +567,13 @@ int w_setColor(lua_State *L)
 		c.b = (unsigned char)luaL_checkint(L, 3);
 		c.a = (unsigned char)luaL_optint(L, 4, 255);
 	}
-	instance->setColor(c);
+	instance()->setColor(c);
 	return 0;
 }
 
 int w_getColor(lua_State *L)
 {
-	Color c = instance->getColor();
+	Color c = instance()->getColor();
 	lua_pushinteger(L, c.r);
 	lua_pushinteger(L, c.g);
 	lua_pushinteger(L, c.b);
@@ -603,13 +603,13 @@ int w_setBackgroundColor(lua_State *L)
 		c.b = (unsigned char)luaL_checkint(L, 3);
 		c.a = (unsigned char)luaL_optint(L, 4, 255);
 	}
-	instance->setBackgroundColor(c);
+	instance()->setBackgroundColor(c);
 	return 0;
 }
 
 int w_getBackgroundColor(lua_State *L)
 {
-	Color c = instance->getBackgroundColor();
+	Color c = instance()->getBackgroundColor();
 	lua_pushinteger(L, c.r);
 	lua_pushinteger(L, c.g);
 	lua_pushinteger(L, c.b);
@@ -620,13 +620,13 @@ int w_getBackgroundColor(lua_State *L)
 int w_setFont(lua_State *L)
 {
 	Font *font = luax_checktype<Font>(L, 1, "Font", GRAPHICS_FONT_T);
-	instance->setFont(font);
+	instance()->setFont(font);
 	return 0;
 }
 
 int w_getFont(lua_State *L)
 {
-	Font *f = instance->getFont();
+	Font *f = instance()->getFont();
 
 	if (f == 0)
 		return 0;
@@ -652,14 +652,14 @@ int w_setColorMask(lua_State *L)
 	}
 
 	// r, g, b, a
-	instance->setColorMask(mask[0], mask[1], mask[2], mask[3]);
+	instance()->setColorMask(mask[0], mask[1], mask[2], mask[3]);
 
 	return 0;
 }
 
 int w_getColorMask(lua_State *L)
 {
-	const bool *mask = instance->getColorMask();
+	const bool *mask = instance()->getColorMask();
 
 	for (int i = 0; i < 4; i++)
 		luax_pushboolean(L, mask[i]);
@@ -674,7 +674,7 @@ int w_setBlendMode(lua_State *L)
 	if (!Graphics::getConstant(str, mode))
 		return luaL_error(L, "Invalid blend mode: %s", str);
 
-	luax_catchexcept(L, [&](){ instance->setBlendMode(mode); });
+	luax_catchexcept(L, [&](){ instance()->setBlendMode(mode); });
 	return 0;
 }
 
@@ -683,7 +683,7 @@ int w_getBlendMode(lua_State *L)
 	const char *str;
 	Graphics::BlendMode mode;
 
-	luax_catchexcept(L, [&](){ mode = instance->getBlendMode(); });
+	luax_catchexcept(L, [&](){ mode = instance()->getBlendMode(); });
 
 	if (!Graphics::getConstant(mode, str))
 		return luaL_error(L, "Unknown blend mode");
@@ -712,14 +712,14 @@ int w_setDefaultFilter(lua_State *L)
 	f.mag = mag;
 	f.anisotropy = anisotropy;
 
-	instance->setDefaultFilter(f);
+	instance()->setDefaultFilter(f);
 	
 	return 0;
 }
 
 int w_getDefaultFilter(lua_State *L)
 {
-	const Texture::Filter &f = instance->getDefaultFilter();
+	const Texture::Filter &f = instance()->getDefaultFilter();
 	const char *minstr;
 	const char *magstr;
 	if (!Texture::getConstant(f.min, minstr))
@@ -744,7 +744,7 @@ int w_setDefaultMipmapFilter(lua_State *L)
 
 	float sharpness = (float) luaL_optnumber(L, 2, 0);
 
-	instance->setDefaultMipmapFilter(filter, sharpness);
+	instance()->setDefaultMipmapFilter(filter, sharpness);
 
 	return 0;
 }
@@ -754,7 +754,7 @@ int w_getDefaultMipmapFilter(lua_State *L)
 	Texture::FilterMode filter;
 	float sharpness;
 
-	instance->getDefaultMipmapFilter(&filter, &sharpness);
+	instance()->getDefaultMipmapFilter(&filter, &sharpness);
 
 	const char *str;
 	if (Texture::getConstant(filter, str))
@@ -770,7 +770,7 @@ int w_getDefaultMipmapFilter(lua_State *L)
 int w_setLineWidth(lua_State *L)
 {
 	float width = (float)luaL_checknumber(L, 1);
-	instance->setLineWidth(width);
+	instance()->setLineWidth(width);
 	return 0;
 }
 
@@ -781,7 +781,7 @@ int w_setLineStyle(lua_State *L)
 	if (!Graphics::getConstant(str, style))
 		return luaL_error(L, "Invalid line style: %s", str);
 
-	instance->setLineStyle(style);
+	instance()->setLineStyle(style);
 	return 0;
 }
 
@@ -792,19 +792,19 @@ int w_setLineJoin(lua_State *L)
 	if (!Graphics::getConstant(str, join))
 		return luaL_error(L, "Invalid line join mode: %s", str);
 
-	instance->setLineJoin(join);
+	instance()->setLineJoin(join);
 	return 0;
 }
 
 int w_getLineWidth(lua_State *L)
 {
-	lua_pushnumber(L, instance->getLineWidth());
+	lua_pushnumber(L, instance()->getLineWidth());
 	return 1;
 }
 
 int w_getLineStyle(lua_State *L)
 {
-	Graphics::LineStyle style = instance->getLineStyle();
+	Graphics::LineStyle style = instance()->getLineStyle();
 	const char *str;
 	if (!Graphics::getConstant(style, str))
 		return luaL_error(L, "Unknown line style");
@@ -814,7 +814,7 @@ int w_getLineStyle(lua_State *L)
 
 int w_getLineJoin(lua_State *L)
 {
-	Graphics::LineJoin join = instance->getLineJoin();
+	Graphics::LineJoin join = instance()->getLineJoin();
 	const char *str;
 	if (!Graphics::getConstant(join, str))
 		return luaL_error(L, "Unknown line join");
@@ -825,7 +825,7 @@ int w_getLineJoin(lua_State *L)
 int w_setPointSize(lua_State *L)
 {
 	float size = (float)luaL_checknumber(L, 1);
-	instance->setPointSize(size);
+	instance()->setPointSize(size);
 	return 0;
 }
 
@@ -837,19 +837,19 @@ int w_setPointStyle(lua_State *L)
 	if (!Graphics::getConstant(str, style))
 		return luaL_error(L, "Invalid point style: %s", str);
 
-	instance->setPointStyle(style);
+	instance()->setPointStyle(style);
 	return 0;
 }
 
 int w_getPointSize(lua_State *L)
 {
-	lua_pushnumber(L, instance->getPointSize());
+	lua_pushnumber(L, instance()->getPointSize());
 	return 1;
 }
 
 int w_getPointStyle(lua_State *L)
 {
-	Graphics::PointStyle style = instance->getPointStyle();
+	Graphics::PointStyle style = instance()->getPointStyle();
 	const char *str;
 	if (!Graphics::getConstant(style, str))
 		return luaL_error(L, "Unknown point style");
@@ -859,19 +859,19 @@ int w_getPointStyle(lua_State *L)
 
 int w_getMaxPointSize(lua_State *L)
 {
-	lua_pushnumber(L, instance->getSystemLimit(Graphics::LIMIT_POINT_SIZE));
+	lua_pushnumber(L, instance()->getSystemLimit(Graphics::LIMIT_POINT_SIZE));
 	return 1;
 }
 
 int w_setWireframe(lua_State *L)
 {
-	instance->setWireframe(luax_toboolean(L, 1));
+	instance()->setWireframe(luax_toboolean(L, 1));
 	return 0;
 }
 
 int w_isWireframe(lua_State *L)
 {
-	luax_pushboolean(L, instance->isWireframe());
+	luax_pushboolean(L, instance()->isWireframe());
 	return 1;
 }
 
@@ -881,7 +881,7 @@ int w_newScreenshot(lua_State *L)
 	bool copyAlpha = luax_optboolean(L, 1, false);
 	love::image::ImageData *i = 0;
 
-	luax_catchexcept(L, [&](){ i = instance->newScreenshot(image, copyAlpha); });
+	luax_catchexcept(L, [&](){ i = instance()->newScreenshot(image, copyAlpha); });
 
 	luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, i);
 	return 1;
@@ -890,7 +890,7 @@ int w_newScreenshot(lua_State *L)
 int w_setCanvas(lua_State *L)
 {
 	// discard stencil testing
-	instance->discardStencil();
+	instance()->discardStencil();
 
 	// called with none -> reset to default buffer
 	if (lua_isnoneornil(L,1))
@@ -997,7 +997,7 @@ int w_isSupported(lua_State *L)
 		if (!Graphics::getConstant(str, feature))
 			return luaL_error(L, "Invalid graphics feature: %s", str);
 
-		if (!instance->isSupported(feature))
+		if (!instance()->isSupported(feature))
 		{
 			supported = false;
 			break;
@@ -1052,7 +1052,7 @@ int w_getCompressedImageFormats(lua_State *L)
 int w_getRendererInfo(lua_State *L)
 {
 	Graphics::RendererInfo info;
-	luax_catchexcept(L, [&](){ info = instance->getRendererInfo(); });
+	luax_catchexcept(L, [&](){ info = instance()->getRendererInfo(); });
 
 	luax_pushstring(L, info.name);
 	luax_pushstring(L, info.version);
@@ -1069,7 +1069,7 @@ int w_getSystemLimit(lua_State *L)
 	if (!Graphics::getConstant(limitstr, limittype))
 		return luaL_error(L, "Invalid system limit type: %s", limitstr);
 
-	lua_pushnumber(L, instance->getSystemLimit(limittype));
+	lua_pushnumber(L, instance()->getSystemLimit(limittype));
 	return 1;
 }
 
@@ -1128,7 +1128,7 @@ int w_print(lua_State *L)
 	float ky = (float)luaL_optnumber(L, 10, 0.0f);
 
 	luax_catchexcept(L,
-		[&](){ instance->print(str, x, y, angle, sx, sy, ox, oy, kx,ky); }
+		[&](){ instance()->print(str, x, y, angle, sx, sy, ox, oy, kx,ky); }
 	);
 	return 0;
 }
@@ -1166,7 +1166,7 @@ int w_printf(lua_State *L)
 	}
 
 	luax_catchexcept(L,
-		[&](){ instance->printf(str, x, y, wrap, align, angle, sx, sy, ox, oy, kx, ky); }
+		[&](){ instance()->printf(str, x, y, wrap, align, angle, sx, sy, ox, oy, kx, ky); }
 	);
 	return 0;
 }
@@ -1175,7 +1175,7 @@ int w_point(lua_State *L)
 {
 	float x = (float)luaL_checknumber(L, 1);
 	float y = (float)luaL_checknumber(L, 2);
-	instance->point(x, y);
+	instance()->point(x, y);
 	return 0;
 }
 
@@ -1210,7 +1210,7 @@ int w_line(lua_State *L)
 			coords[i] = luax_tofloat(L, i + 1);
 	}
 
-	instance->polyline(coords, args);
+	instance()->polyline(coords, args);
 
 	delete[] coords;
 	return 0;
@@ -1227,7 +1227,7 @@ int w_rectangle(lua_State *L)
 	float y = (float)luaL_checknumber(L, 3);
 	float w = (float)luaL_checknumber(L, 4);
 	float h = (float)luaL_checknumber(L, 5);
-	instance->rectangle(mode, x, y, w, h);
+	instance()->rectangle(mode, x, y, w, h);
 	return 0;
 }
 
@@ -1247,7 +1247,7 @@ int w_circle(lua_State *L)
 	else
 		points = luaL_checkint(L, 5);
 
-	instance->circle(mode, x, y, radius, points);
+	instance()->circle(mode, x, y, radius, points);
 	return 0;
 }
 
@@ -1269,7 +1269,7 @@ int w_arc(lua_State *L)
 	else
 		points = luaL_checkint(L, 7);
 
-	instance->arc(mode, x, y, radius, angle1, angle2, points);
+	instance()->arc(mode, x, y, radius, angle1, angle2, points);
 	return 0;
 }
 
@@ -1315,7 +1315,7 @@ int w_polygon(lua_State *L)
 	// make a closed loop
 	coords[args]   = coords[0];
 	coords[args+1] = coords[1];
-	instance->polygon(mode, coords, args+2);
+	instance()->polygon(mode, coords, args+2);
 	delete[] coords;
 
 	return 0;
@@ -1323,20 +1323,20 @@ int w_polygon(lua_State *L)
 
 int w_push(lua_State *L)
 {
-	luax_catchexcept(L, [&](){ instance->push(); });
+	luax_catchexcept(L, [&](){ instance()->push(); });
 	return 0;
 }
 
 int w_pop(lua_State *L)
 {
-	luax_catchexcept(L, [&](){ instance->pop(); });
+	luax_catchexcept(L, [&](){ instance()->pop(); });
 	return 0;
 }
 
 int w_rotate(lua_State *L)
 {
 	float angle = (float)luaL_checknumber(L, 1);
-	instance->rotate(angle);
+	instance()->rotate(angle);
 	return 0;
 }
 
@@ -1344,7 +1344,7 @@ int w_scale(lua_State *L)
 {
 	float sx = (float)luaL_optnumber(L, 1, 1.0f);
 	float sy = (float)luaL_optnumber(L, 2, sx);
-	instance->scale(sx, sy);
+	instance()->scale(sx, sy);
 	return 0;
 }
 
@@ -1352,7 +1352,7 @@ int w_translate(lua_State *L)
 {
 	float x = (float)luaL_checknumber(L, 1);
 	float y = (float)luaL_checknumber(L, 2);
-	instance->translate(x, y);
+	instance()->translate(x, y);
 	return 0;
 }
 
@@ -1360,13 +1360,13 @@ int w_shear(lua_State *L)
 {
 	float kx = (float)luaL_checknumber(L, 1);
 	float ky = (float)luaL_checknumber(L, 2);
-	instance->shear(kx, ky);
+	instance()->shear(kx, ky);
 	return 0;
 }
 
 int w_origin(lua_State * /*L*/)
 {
-	instance->origin();
+	instance()->origin();
 	return 0;
 }
 
@@ -1484,7 +1484,8 @@ static const lua_CFunction types[] =
 
 extern "C" int luaopen_love_graphics(lua_State *L)
 {
-	if (instance == 0)
+	Graphics *instance = instance();
+	if (instance == nullptr)
 	{
 		luax_catchexcept(L, [&](){ instance = new Graphics(); });
 	}

+ 1 - 3
src/modules/image/Image.h

@@ -44,9 +44,7 @@ class Image : public Module
 {
 public:
 
-	/**
-	 * Destructor.
-	 **/
+	Image() { moduleType = M_IMAGE; }
 	virtual ~Image() {}
 
 	/**

+ 6 - 5
src/modules/image/wrap_Image.cpp

@@ -32,7 +32,7 @@ namespace love
 namespace image
 {
 
-static Image *instance = nullptr;
+#define instance() (Module::getInstance<Image>(Module::M_IMAGE))
 
 int w_newImageData(lua_State *L)
 {
@@ -45,7 +45,7 @@ int w_newImageData(lua_State *L)
 			return luaL_error(L, "Invalid image size.");
 
 		ImageData *t = nullptr;
-		luax_catchexcept(L, [&](){ t = instance->newImageData(w, h); });
+		luax_catchexcept(L, [&](){ t = instance()->newImageData(w, h); });
 
 		luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, t);
 		return 1;
@@ -56,7 +56,7 @@ int w_newImageData(lua_State *L)
 
 	ImageData *t = nullptr;
 	luax_catchexcept(L,
-		[&]() { t = instance->newImageData(data); },
+		[&]() { t = instance()->newImageData(data); },
 		[&]() { data->release(); }
 	);
 
@@ -70,7 +70,7 @@ int w_newCompressedData(lua_State *L)
 
 	CompressedData *t = nullptr;
 	luax_catchexcept(L,
-		[&]() { t = instance->newCompressedData(data); },
+		[&]() { t = instance()->newCompressedData(data); },
 		[&]() { data->release(); }
 	);
 
@@ -81,7 +81,7 @@ int w_newCompressedData(lua_State *L)
 int w_isCompressed(lua_State *L)
 {
 	love::filesystem::FileData *data = love::filesystem::luax_getfiledata(L, 1);
-	bool compressed = instance->isCompressed(data);
+	bool compressed = instance()->isCompressed(data);
 	data->release();
 
 	luax_pushboolean(L, compressed);
@@ -106,6 +106,7 @@ static const lua_CFunction types[] =
 
 extern "C" int luaopen_love_image(lua_State *L)
 {
+	Image *instance = instance();
 	if (instance == nullptr)
 	{
 		luax_catchexcept(L, [&](){ instance = new love::image::magpie::Image(); });

+ 1 - 0
src/modules/joystick/JoystickModule.h

@@ -34,6 +34,7 @@ class JoystickModule : public Module
 {
 public:
 
+	JoystickModule() { moduleType = M_JOYSTICK; }
 	virtual ~JoystickModule() {}
 
 	/**

+ 10 - 9
src/modules/joystick/wrap_JoystickModule.cpp

@@ -30,16 +30,16 @@ namespace love
 namespace joystick
 {
 
-static JoystickModule *instance = nullptr;
+#define instance() (Module::getInstance<JoystickModule>(Module::M_JOYSTICK))
 
 int w_getJoysticks(lua_State *L)
 {
-	int stickcount = instance->getJoystickCount();
+	int stickcount = instance()->getJoystickCount();
 	lua_createtable(L, stickcount, 0);
 
 	for (int i = 0; i < stickcount; i++)
 	{
-		Joystick *stick = instance->getJoystick(i);
+		Joystick *stick = instance()->getJoystick(i);
 		stick->retain();
 		luax_pushtype(L, "Joystick", JOYSTICK_JOYSTICK_T, stick);
 		lua_rawseti(L, -2, i + 1);
@@ -51,7 +51,7 @@ int w_getJoysticks(lua_State *L)
 int w_getIndex(lua_State *L)
 {
 	Joystick *j = luax_checkjoystick(L, 1);
-	int index = instance->getIndex(j);
+	int index = instance()->getIndex(j);
 	if (index >= 0)
 		lua_pushinteger(L, index + 1);
 	else
@@ -61,7 +61,7 @@ int w_getIndex(lua_State *L)
 
 int w_getJoystickCount(lua_State *L)
 {
-	lua_pushinteger(L, instance->getJoystickCount());
+	lua_pushinteger(L, instance()->getJoystickCount());
 	return 1;
 }
 
@@ -109,7 +109,7 @@ int w_setGamepadMapping(lua_State *L)
 	}
 
 	bool success = false;
-	luax_catchexcept(L, [&](){ success = instance->setGamepadMapping(guid, gpinput, jinput); });
+	luax_catchexcept(L, [&](){ success = instance()->setGamepadMapping(guid, gpinput, jinput); });
 
 	luax_pushboolean(L, success);
 	return 1;
@@ -142,7 +142,7 @@ int w_getGamepadMapping(lua_State *L)
 	Joystick::JoystickInput jinput;
 	jinput.type = Joystick::INPUT_TYPE_MAX_ENUM;
 
-	luax_catchexcept(L, [&](){ jinput = instance->getGamepadMapping(guid, gpinput); });
+	luax_catchexcept(L, [&](){ jinput = instance()->getGamepadMapping(guid, gpinput); });
 
 	if (jinput.type == Joystick::INPUT_TYPE_MAX_ENUM)
 		return 0;
@@ -197,14 +197,14 @@ int w_loadGamepadMappings(lua_State *L)
 	else
 		mappings = luax_checkstring(L, 1);
 
-	luax_catchexcept(L, [&](){ instance->loadGamepadMappings(mappings); });
+	luax_catchexcept(L, [&](){ instance()->loadGamepadMappings(mappings); });
 	return 0;
 }
 
 int w_saveGamepadMappings(lua_State *L)
 {
 	lua_settop(L, 1);
-	std::string mappings = instance->saveGamepadMappings();
+	std::string mappings = instance()->saveGamepadMappings();
 
 	// Optionally write the mappings string to a file.
 	if (!lua_isnoneornil(L, 1))
@@ -240,6 +240,7 @@ static const lua_CFunction types[] =
 
 extern "C" int luaopen_love_joystick(lua_State *L)
 {
+	JoystickModule *instance = instance();
 	if (instance == nullptr)
 	{
 		luax_catchexcept(L, [&](){ instance = new sdl::JoystickModule(); });

+ 5 - 0
src/modules/keyboard/Keyboard.cpp

@@ -27,6 +27,11 @@ namespace love
 namespace keyboard
 {
 
+Keyboard::Keyboard()
+{
+	moduleType = M_KEYBOARD;
+}
+
 bool Keyboard::getConstant(const char *in, Keyboard::Key &out)
 {
 	return keys.find(in, out);

+ 1 - 0
src/modules/keyboard/Keyboard.h

@@ -244,6 +244,7 @@ public:
 		KEY_MAX_ENUM = 512
 	};
 
+	Keyboard();
 	virtual ~Keyboard() {}
 
 	/**

+ 7 - 6
src/modules/keyboard/wrap_Keyboard.cpp

@@ -29,17 +29,17 @@ namespace love
 namespace keyboard
 {
 
-static Keyboard *instance = nullptr;
+#define instance() (Module::getInstance<Keyboard>(Module::M_KEYBOARD))
 
 int w_setKeyRepeat(lua_State *L)
 {
-	instance->setKeyRepeat(luax_toboolean(L, 1));
+	instance()->setKeyRepeat(luax_toboolean(L, 1));
 	return 0;
 }
 
 int w_hasKeyRepeat(lua_State *L)
 {
-	luax_pushboolean(L, instance->hasKeyRepeat());
+	luax_pushboolean(L, instance()->hasKeyRepeat());
 	return 1;
 }
 
@@ -57,20 +57,20 @@ int w_isDown(lua_State *L)
 	}
 	keylist[counter] = Keyboard::KEY_MAX_ENUM;
 
-	luax_pushboolean(L, instance->isDown(keylist));
+	luax_pushboolean(L, instance()->isDown(keylist));
 	delete[] keylist;
 	return 1;
 }
 
 int w_setTextInput(lua_State *L)
 {
-	instance->setTextInput(luax_toboolean(L, 1));
+	instance()->setTextInput(luax_toboolean(L, 1));
 	return 0;
 }
 
 int w_hasTextInput(lua_State *L)
 {
-	luax_pushboolean(L, instance->hasTextInput());
+	luax_pushboolean(L, instance()->hasTextInput());
 	return 1;
 }
 
@@ -87,6 +87,7 @@ static const luaL_Reg functions[] =
 
 extern "C" int luaopen_love_keyboard(lua_State *L)
 {
+	Keyboard *instance = instance();
 	if (instance == nullptr)
 	{
 		luax_catchexcept(L, [&](){ instance = new love::keyboard::sdl::Keyboard(); });

+ 2 - 0
src/modules/math/MathModule.cpp

@@ -87,6 +87,8 @@ Math Math::instance;
 Math::Math()
 	: rng()
 {
+	moduleType = M_MATH;
+
 	// prevent the runtime from free()-ing this
 	retain();
 }

+ 5 - 0
src/modules/mouse/Mouse.cpp

@@ -25,6 +25,11 @@ namespace love
 namespace mouse
 {
 
+Mouse::Mouse()
+{
+	moduleType = M_MOUSE;
+}
+
 bool Mouse::getConstant(const char *in, Button &out)
 {
 	return buttons.find(in, out);

+ 1 - 0
src/modules/mouse/Mouse.h

@@ -49,6 +49,7 @@ public:
 		BUTTON_MAX_ENUM
 	};
 
+	Mouse();
 	virtual ~Mouse() {}
 
 	virtual Cursor *newCursor(love::image::ImageData *data, int hotx, int hoty) = 0;

+ 18 - 17
src/modules/mouse/wrap_Mouse.cpp

@@ -30,7 +30,7 @@ namespace love
 namespace mouse
 {
 
-static Mouse *instance = nullptr;
+#define instance() (Module::getInstance<Mouse>(Module::M_MOUSE))
 
 int w_newCursor(lua_State *L)
 {
@@ -43,7 +43,7 @@ int w_newCursor(lua_State *L)
 	int hotx = luaL_optint(L, 2, 0);
 	int hoty = luaL_optint(L, 3, 0);
 
-	luax_catchexcept(L, [&](){ cursor = instance->newCursor(data, hotx, hoty); });
+	luax_catchexcept(L, [&](){ cursor = instance()->newCursor(data, hotx, hoty); });
 
 	luax_pushtype(L, "Cursor", MOUSE_CURSOR_T, cursor);
 	return 1;
@@ -58,7 +58,7 @@ int w_getSystemCursor(lua_State *L)
 		return luaL_error(L, "Invalid system cursor type: %s", str);
 
 	Cursor *cursor = 0;
-	luax_catchexcept(L, [&](){ cursor = instance->getSystemCursor(systemCursor); });
+	luax_catchexcept(L, [&](){ cursor = instance()->getSystemCursor(systemCursor); });
 
 	cursor->retain();
 	luax_pushtype(L, "Cursor", MOUSE_CURSOR_T, cursor);
@@ -70,18 +70,18 @@ int w_setCursor(lua_State *L)
 	// Revert to the default system cursor if no argument is given.
 	if (lua_isnoneornil(L, 1))
 	{
-		instance->setCursor();
+		instance()->setCursor();
 		return 0;
 	}
 
 	Cursor *cursor = luax_checkcursor(L, 1);
-	instance->setCursor(cursor);
+	instance()->setCursor(cursor);
 	return 0;
 }
 
 int w_getCursor(lua_State *L)
 {
-	Cursor *cursor = instance->getCursor();
+	Cursor *cursor = instance()->getCursor();
 
 	if (cursor)
 	{
@@ -96,20 +96,20 @@ int w_getCursor(lua_State *L)
 
 int w_getX(lua_State *L)
 {
-	lua_pushnumber(L, instance->getX());
+	lua_pushnumber(L, instance()->getX());
 	return 1;
 }
 
 int w_getY(lua_State *L)
 {
-	lua_pushnumber(L, instance->getY());
+	lua_pushnumber(L, instance()->getY());
 	return 1;
 }
 
 int w_getPosition(lua_State *L)
 {
 	int x, y;
-	instance->getPosition(x, y);
+	instance()->getPosition(x, y);
 	lua_pushinteger(L, x);
 	lua_pushinteger(L, y);
 	return 2;
@@ -118,14 +118,14 @@ int w_getPosition(lua_State *L)
 int w_setX(lua_State *L)
 {
 	int x = luaL_checkint(L, 1);
-	instance->setX(x);
+	instance()->setX(x);
 	return 0;
 }
 
 int w_setY(lua_State *L)
 {
 	int y = luaL_checkint(L, 1);
-	instance->setY(y);
+	instance()->setY(y);
 	return 0;
 }
 
@@ -133,7 +133,7 @@ int w_setPosition(lua_State *L)
 {
 	int x = luaL_checkint(L, 1);
 	int y = luaL_checkint(L, 2);
-	instance->setPosition(x, y);
+	instance()->setPosition(x, y);
 	return 0;
 }
 
@@ -151,7 +151,7 @@ int w_isDown(lua_State *L)
 	}
 	buttonlist[counter] = Mouse::BUTTON_MAX_ENUM;
 
-	luax_pushboolean(L, instance->isDown(buttonlist));
+	luax_pushboolean(L, instance()->isDown(buttonlist));
 	delete[] buttonlist;
 	return 1;
 }
@@ -159,26 +159,26 @@ int w_isDown(lua_State *L)
 int w_setVisible(lua_State *L)
 {
 	bool b = luax_toboolean(L, 1);
-	instance->setVisible(b);
+	instance()->setVisible(b);
 	return 0;
 }
 
 int w_isVisible(lua_State *L)
 {
-	luax_pushboolean(L, instance->isVisible());
+	luax_pushboolean(L, instance()->isVisible());
 	return 1;
 }
 
 int w_setGrabbed(lua_State *L)
 {
 	bool b = luax_toboolean(L, 1);
-	instance->setGrabbed(b);
+	instance()->setGrabbed(b);
 	return 0;
 }
 
 int w_isGrabbed(lua_State *L)
 {
-	luax_pushboolean(L, instance->isGrabbed());
+	luax_pushboolean(L, instance()->isGrabbed());
 	return 1;
 }
 
@@ -212,6 +212,7 @@ static const lua_CFunction types[] =
 
 extern "C" int luaopen_love_mouse(lua_State *L)
 {
+	Mouse *instance = instance();
 	if (instance == nullptr)
 	{
 		luax_catchexcept(L, [&](){ instance = new love::mouse::sdl::Mouse(); });

+ 5 - 0
src/modules/physics/box2d/Physics.cpp

@@ -33,6 +33,11 @@ namespace box2d
 
 int Physics::meter = Physics::DEFAULT_METER;
 
+Physics::Physics()
+{
+	moduleType = M_PHYSICS;
+}
+
 const char *Physics::getName() const
 {
 	return "love.physics.box2d";

+ 2 - 0
src/modules/physics/box2d/Physics.h

@@ -61,6 +61,8 @@ public:
 	 **/
 	static const int DEFAULT_METER = 30;
 
+	Physics();
+
 	// Implements Module.
 	const char *getName() const;
 

+ 26 - 24
src/modules/physics/box2d/wrap_Physics.cpp

@@ -50,6 +50,7 @@ namespace box2d
 {
 
 static Physics *instance = 0;
+#define instance() (Module::getInstance<Physics>(Module::M_PHYSICS))
 
 int w_newWorld(lua_State *L)
 {
@@ -58,7 +59,7 @@ int w_newWorld(lua_State *L)
 	bool sleep = luax_optboolean(L, 3, true);
 
 	World *w;
-	luax_catchexcept(L, [&](){ w = instance->newWorld(gx, gy, sleep); });
+	luax_catchexcept(L, [&](){ w = instance()->newWorld(gx, gy, sleep); });
 	luax_pushtype(L, "World", PHYSICS_WORLD_T, w);
 
 	return 1;
@@ -76,7 +77,7 @@ int w_newBody(lua_State *L)
 		return luaL_error(L, "Invalid Body type: %s", typestr);
 
 	Body *body;
-	luax_catchexcept(L, [&](){ body = instance->newBody(world, x, y, btype); });
+	luax_catchexcept(L, [&](){ body = instance()->newBody(world, x, y, btype); });
 	luax_pushtype(L, "Body", PHYSICS_BODY_T, body);
 	return 1;
 }
@@ -87,7 +88,7 @@ int w_newFixture(lua_State *L)
 	Shape *shape = luax_checkshape(L, 2);
 	float density = (float)luaL_optnumber(L, 3, 1.0f);
 	Fixture *fixture;
-	luax_catchexcept(L, [&](){ fixture = instance->newFixture(body, shape, density); });
+	luax_catchexcept(L, [&](){ fixture = instance()->newFixture(body, shape, density); });
 	luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, fixture);
 	return 1;
 }
@@ -100,7 +101,7 @@ int w_newCircleShape(lua_State *L)
 	{
 		float radius = (float)luaL_checknumber(L, 1);
 		CircleShape *shape;
-		luax_catchexcept(L, [&](){ shape = instance->newCircleShape(radius); });
+		luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(radius); });
 		luax_pushtype(L, "CircleShape", PHYSICS_CIRCLE_SHAPE_T, shape);
 		return 1;
 	}
@@ -110,7 +111,7 @@ int w_newCircleShape(lua_State *L)
 		float y = (float)luaL_checknumber(L, 2);
 		float radius = (float)luaL_checknumber(L, 3);
 		CircleShape *shape;
-		luax_catchexcept(L, [&](){ shape = instance->newCircleShape(x, y, radius); });
+		luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(x, y, radius); });
 		luax_pushtype(L, "CircleShape", PHYSICS_CIRCLE_SHAPE_T, shape);
 		return 1;
 	}
@@ -127,7 +128,7 @@ int w_newRectangleShape(lua_State *L)
 		float w = (float)luaL_checknumber(L, 1);
 		float h = (float)luaL_checknumber(L, 2);
 		PolygonShape *shape;
-		luax_catchexcept(L, [&](){ shape = instance->newRectangleShape(w, h); });
+		luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(w, h); });
 		luax_pushtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, shape);
 		return 1;
 	}
@@ -139,7 +140,7 @@ int w_newRectangleShape(lua_State *L)
 		float h = (float)luaL_checknumber(L, 4);
 		float angle = (float)luaL_optnumber(L, 5, 0);
 		PolygonShape *shape;
-		luax_catchexcept(L, [&](){ shape = instance->newRectangleShape(x, y, w, h, angle); });
+		luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(x, y, w, h, angle); });
 		luax_pushtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, shape);
 		return 1;
 	}
@@ -154,7 +155,7 @@ int w_newEdgeShape(lua_State *L)
 	float x2 = (float)luaL_checknumber(L, 3);
 	float y2 = (float)luaL_checknumber(L, 4);
 	EdgeShape *shape;
-	luax_catchexcept(L, [&](){ shape = instance->newEdgeShape(x1, y1, x2, y2); });
+	luax_catchexcept(L, [&](){ shape = instance()->newEdgeShape(x1, y1, x2, y2); });
 	luax_pushtype(L, "EdgeShape", PHYSICS_EDGE_SHAPE_T, shape);
 	return 1;
 }
@@ -162,14 +163,14 @@ int w_newEdgeShape(lua_State *L)
 int w_newPolygonShape(lua_State *L)
 {
 	int ret = 0;
-	luax_catchexcept(L, [&](){ ret = instance->newPolygonShape(L); });
+	luax_catchexcept(L, [&](){ ret = instance()->newPolygonShape(L); });
 	return ret;
 }
 
 int w_newChainShape(lua_State *L)
 {
 	int ret = 0;
-	luax_catchexcept(L, [&](){ ret = instance->newChainShape(L); });
+	luax_catchexcept(L, [&](){ ret = instance()->newChainShape(L); });
 	return ret;
 }
 
@@ -184,7 +185,7 @@ int w_newDistanceJoint(lua_State *L)
 	bool collideConnected = luax_optboolean(L, 7, false);
 	DistanceJoint *j;
 	luax_catchexcept(L, [&]() {
-		j = instance->newDistanceJoint(body1, body2, x1, y1, x2, y2, collideConnected);
+		j = instance()->newDistanceJoint(body1, body2, x1, y1, x2, y2, collideConnected);
 	});
 	luax_pushtype(L, "DistanceJoint", PHYSICS_DISTANCE_JOINT_T, j);
 	return 1;
@@ -196,7 +197,7 @@ int w_newMouseJoint(lua_State *L)
 	float x = (float)luaL_checknumber(L, 2);
 	float y = (float)luaL_checknumber(L, 3);
 	MouseJoint *j;
-	luax_catchexcept(L, [&](){ j = instance->newMouseJoint(body, x, y); });
+	luax_catchexcept(L, [&](){ j = instance()->newMouseJoint(body, x, y); });
 	luax_pushtype(L, "MouseJoint", PHYSICS_MOUSE_JOINT_T, j);
 	return 1;
 }
@@ -210,7 +211,7 @@ int w_newRevoluteJoint(lua_State *L)
 	bool collideConnected = luax_optboolean(L, 5, false);
 	RevoluteJoint *j;
 	luax_catchexcept(L, [&]() {
-		j = instance->newRevoluteJoint(body1, body2, x, y, collideConnected);
+		j = instance()->newRevoluteJoint(body1, body2, x, y, collideConnected);
 	});
 	luax_pushtype(L, "RevoluteJoint", PHYSICS_REVOLUTE_JOINT_T, j);
 	return 1;
@@ -242,7 +243,7 @@ int w_newPrismaticJoint(lua_State *L)
 	}
 	PrismaticJoint *j;
 	luax_catchexcept(L, [&]() {
-		j = instance->newPrismaticJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);
+		j = instance()->newPrismaticJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);
 	});
 	luax_pushtype(L, "PrismaticJoint", PHYSICS_PRISMATIC_JOINT_T, j);
 	return 1;
@@ -265,7 +266,7 @@ int w_newPulleyJoint(lua_State *L)
 
 	PulleyJoint *j;
 	luax_catchexcept(L, [&]() {
-		j = instance->newPulleyJoint(body1, body2, b2Vec2(gx1,gy1), b2Vec2(gx2,gy2), b2Vec2(x1,y1), b2Vec2(x2,y2), ratio, collideConnected);
+		j = instance()->newPulleyJoint(body1, body2, b2Vec2(gx1,gy1), b2Vec2(gx2,gy2), b2Vec2(x1,y1), b2Vec2(x2,y2), ratio, collideConnected);
 	});
 	luax_pushtype(L, "PulleyJoint", PHYSICS_PULLEY_JOINT_T, j);
 	return 1;
@@ -280,7 +281,7 @@ int w_newGearJoint(lua_State *L)
 
 	GearJoint *j;
 	luax_catchexcept(L, [&]() {
-		j = instance->newGearJoint(joint1, joint2, ratio, collideConnected);
+		j = instance()->newGearJoint(joint1, joint2, ratio, collideConnected);
 	});
 	luax_pushtype(L, "GearJoint", PHYSICS_GEAR_JOINT_T, j);
 	return 1;
@@ -308,7 +309,7 @@ int w_newFrictionJoint(lua_State *L)
 	}
 	FrictionJoint *j;
 	luax_catchexcept(L, [&]() {
-		j = instance->newFrictionJoint(body1, body2, xA, yA, xB, yB, collideConnected);
+		j = instance()->newFrictionJoint(body1, body2, xA, yA, xB, yB, collideConnected);
 	});
 	luax_pushtype(L, "FrictionJoint", PHYSICS_FRICTION_JOINT_T, j);
 	return 1;
@@ -336,7 +337,7 @@ int w_newWeldJoint(lua_State *L)
 	}
 	WeldJoint *j;
 	luax_catchexcept(L, [&]() {
-		j = instance->newWeldJoint(body1, body2, xA, yA, xB, yB, collideConnected);
+		j = instance()->newWeldJoint(body1, body2, xA, yA, xB, yB, collideConnected);
 	});
 	luax_pushtype(L, "WeldJoint", PHYSICS_WELD_JOINT_T, j);
 	return 1;
@@ -369,7 +370,7 @@ int w_newWheelJoint(lua_State *L)
 
 	WheelJoint *j;
 	luax_catchexcept(L, [&]() {
-		j = instance->newWheelJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);
+		j = instance()->newWheelJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);
 	});
 	luax_pushtype(L, "WheelJoint", PHYSICS_WHEEL_JOINT_T, j);
 	return 1;
@@ -387,7 +388,7 @@ int w_newRopeJoint(lua_State *L)
 	bool collideConnected = luax_optboolean(L, 8, false);
 	RopeJoint *j;
 	luax_catchexcept(L, [&]() {
-		j = instance->newRopeJoint(body1, body2, x1, y1, x2, y2, maxLength, collideConnected);
+		j = instance()->newRopeJoint(body1, body2, x1, y1, x2, y2, maxLength, collideConnected);
 	});
 	luax_pushtype(L, "RopeJoint", PHYSICS_ROPE_JOINT_T, j);
 	return 1;
@@ -402,12 +403,12 @@ int w_newMotorJoint(lua_State *L)
 	{
 		float correctionFactor = (float)luaL_checknumber(L, 3);
 		luax_catchexcept(L, [&]() {
-			j = instance->newMotorJoint(body1, body2, correctionFactor);
+			j = instance()->newMotorJoint(body1, body2, correctionFactor);
 		});
 	}
 	else
 	{
-		luax_catchexcept(L, [&](){ j = instance->newMotorJoint(body1, body2); });
+		luax_catchexcept(L, [&](){ j = instance()->newMotorJoint(body1, body2); });
 	}
 	luax_pushtype(L, "MotorJoint", PHYSICS_MOTOR_JOINT_T, j);
 	return 1;
@@ -415,7 +416,7 @@ int w_newMotorJoint(lua_State *L)
 
 int w_getDistance(lua_State *L)
 {
-	return instance->getDistance(L);
+	return instance()->getDistance(L);
 }
 
 int w_setMeter(lua_State *L)
@@ -487,7 +488,8 @@ static const lua_CFunction types[] =
 
 extern "C" int luaopen_love_physics(lua_State *L)
 {
-	if (instance == 0)
+	Physics *instance = instance();
+	if (instance == nullptr)
 	{
 		luax_catchexcept(L, [&](){ instance = new Physics(); });
 	}

+ 5 - 0
src/modules/sound/Sound.cpp

@@ -25,6 +25,11 @@ namespace love
 namespace sound
 {
 
+Sound::Sound()
+{
+	moduleType = M_SOUND;
+}
+
 Sound::~Sound()
 {
 }

+ 1 - 3
src/modules/sound/Sound.h

@@ -42,9 +42,7 @@ class Sound : public Module
 
 public:
 
-	/**
-	 * Destructor.
-	 **/
+	Sound();
 	virtual ~Sound();
 
 	/**

+ 6 - 5
src/modules/sound/wrap_Sound.cpp

@@ -30,7 +30,7 @@ namespace love
 namespace sound
 {
 
-static Sound *instance = 0;
+#define instance() (Module::getInstance<Sound>(Module::M_SOUND))
 
 int w_newSoundData(lua_State *L)
 {
@@ -43,7 +43,7 @@ int w_newSoundData(lua_State *L)
 		int bitDepth = luaL_optint(L, 3, Decoder::DEFAULT_BIT_DEPTH);
 		int channels = luaL_optint(L, 4, Decoder::DEFAULT_CHANNELS);
 
-		luax_catchexcept(L, [&](){ t = instance->newSoundData(samples, sampleRate, bitDepth, channels); });
+		luax_catchexcept(L, [&](){ t = instance()->newSoundData(samples, sampleRate, bitDepth, channels); });
 	}
 	// Must be string or decoder.
 	else
@@ -55,7 +55,7 @@ int w_newSoundData(lua_State *L)
 			lua_replace(L, 1);
 		}
 
-		luax_catchexcept(L, [&](){ t = instance->newSoundData(luax_checkdecoder(L, 1)); });
+		luax_catchexcept(L, [&](){ t = instance()->newSoundData(luax_checkdecoder(L, 1)); });
 	}
 
 	luax_pushtype(L, "SoundData", SOUND_SOUND_DATA_T, t);
@@ -69,7 +69,7 @@ int w_newDecoder(lua_State *L)
 
 	Decoder *t = nullptr;
 	luax_catchexcept(L,
-		[&]() { t = instance->newDecoder(data, bufferSize); },
+		[&]() { t = instance()->newDecoder(data, bufferSize); },
 		[&]() { data->release(); }
 	);
 
@@ -97,7 +97,8 @@ static const lua_CFunction types[] =
 
 extern "C" int luaopen_love_sound(lua_State *L)
 {
-	if (instance == 0)
+	Sound *instance = instance();
+	if (instance == nullptr)
 	{
 		luax_catchexcept(L, [&](){ instance = new lullaby::Sound(); });
 	}

+ 5 - 0
src/modules/system/System.cpp

@@ -41,6 +41,11 @@ namespace love
 namespace system
 {
 
+System::System()
+{
+	moduleType = M_SYSTEM;
+}
+
 std::string System::getOS() const
 {
 #if defined(LOVE_MACOSX)

+ 1 - 0
src/modules/system/System.h

@@ -48,6 +48,7 @@ public:
 		POWER_MAX_ENUM
 	};
 
+	System();
 	virtual ~System() {}
 
 	/**

+ 8 - 7
src/modules/system/wrap_System.cpp

@@ -27,30 +27,30 @@ namespace love
 namespace system
 {
 
-static System *instance = nullptr;
+#define instance() (Module::getInstance<System>(Module::M_SYSTEM))
 
 int w_getOS(lua_State *L)
 {
-	luax_pushstring(L, instance->getOS());
+	luax_pushstring(L, instance()->getOS());
 	return 1;
 }
 
 int w_getProcessorCount(lua_State *L)
 {
-	lua_pushinteger(L, instance->getProcessorCount());
+	lua_pushinteger(L, instance()->getProcessorCount());
 	return 1;
 }
 
 int w_setClipboardText(lua_State *L)
 {
 	const char *text = luaL_checkstring(L, 1);
-	instance->setClipboardText(text);
+	instance()->setClipboardText(text);
 	return 0;
 }
 
 int w_getClipboardText(lua_State *L)
 {
-	luax_pushstring(L, instance->getClipboardText());
+	luax_pushstring(L, instance()->getClipboardText());
 	return 1;
 }
 
@@ -59,7 +59,7 @@ int w_getPowerInfo(lua_State *L)
 	int seconds = -1, percent = -1;
 	const char *str;
 
-	System::PowerState state = instance->getPowerInfo(seconds, percent);
+	System::PowerState state = instance()->getPowerInfo(seconds, percent);
 
 	if (!System::getConstant(state, str))
 		str = "unknown";
@@ -82,7 +82,7 @@ int w_getPowerInfo(lua_State *L)
 int w_openURL(lua_State *L)
 {
 	std::string url = luax_checkstring(L, 1);
-	luax_pushboolean(L, instance->openURL(url));
+	luax_pushboolean(L, instance()->openURL(url));
 	return 1;
 }
 
@@ -99,6 +99,7 @@ static const luaL_Reg functions[] =
 
 extern "C" int luaopen_love_system(lua_State *L)
 {
+	System *instance = instance();
 	if (instance == nullptr)
 	{
 		instance = new love::system::sdl::System();

+ 1 - 1
src/modules/thread/LuaThread.cpp

@@ -107,7 +107,7 @@ void LuaThread::onError()
 	if (error.empty())
 		return;
 
-	event::Event *event = (event::Event *) Module::findInstance("love.event.");
+	event::Event *event = Module::getInstance<event::Event>(Module::M_EVENT);
 	if (!event)
 		return;
 

+ 5 - 0
src/modules/thread/ThreadModule.cpp

@@ -25,6 +25,11 @@ namespace love
 namespace thread
 {
 
+ThreadModule::ThreadModule()
+{
+	moduleType = M_THREAD;
+}
+
 LuaThread *ThreadModule::newThread(const std::string &name, love::Data *data)
 {
 	LuaThread *lt = new LuaThread(name, data);

+ 1 - 0
src/modules/thread/ThreadModule.h

@@ -42,6 +42,7 @@ class ThreadModule : public love::Module
 {
 public:
 
+	ThreadModule();
 	virtual ~ThreadModule() {}
 	virtual LuaThread *newThread(const std::string &name, love::Data *data);
 	virtual Channel *newChannel();

+ 6 - 5
src/modules/thread/wrap_ThreadModule.cpp

@@ -32,7 +32,7 @@ namespace love
 namespace thread
 {
 
-static ThreadModule *instance = 0;
+#define instance() (Module::getInstance<ThreadModule>(Module::M_THREAD))
 
 int w_newThread(lua_State *L)
 {
@@ -53,14 +53,14 @@ int w_newThread(lua_State *L)
 		data = luax_checktype<love::Data>(L, 1, "Data", DATA_T);
 	}
 
-	LuaThread *t = instance->newThread(name, data);
+	LuaThread *t = instance()->newThread(name, data);
 	luax_pushtype(L, "Thread", THREAD_THREAD_T, t);
 	return 1;
 }
 
 int w_newChannel(lua_State *L)
 {
-	Channel *c = instance->newChannel();
+	Channel *c = instance()->newChannel();
 	luax_pushtype(L, "Channel", THREAD_CHANNEL_T, c);
 	return 1;
 }
@@ -68,7 +68,7 @@ int w_newChannel(lua_State *L)
 int w_getChannel(lua_State *L)
 {
 	std::string name = luax_checkstring(L, 1);
-	Channel *c = instance->getChannel(name);
+	Channel *c = instance()->getChannel(name);
 	luax_pushtype(L, "Channel", THREAD_CHANNEL_T, c);
 	return 1;
 }
@@ -89,7 +89,8 @@ static const lua_CFunction types[] = {
 
 extern "C" int luaopen_love_thread(lua_State *L)
 {
-	if (instance == 0)
+	ThreadModule *instance = instance();
+	if (instance == nullptr)
 	{
 		luax_catchexcept(L, [&](){ instance = new love::thread::ThreadModule(); });
 	}

+ 1 - 3
src/modules/timer/Timer.h

@@ -33,9 +33,7 @@ class Timer : public Module
 {
 public:
 
-	/**
-	 * Destructor.
-	 **/
+	Timer() { moduleType = M_TIMER; }
 	virtual ~Timer() {}
 
 	/**

+ 9 - 8
src/modules/timer/wrap_Timer.cpp

@@ -30,41 +30,41 @@ namespace love
 namespace timer
 {
 
-static Timer *instance = 0;
+#define instance() (Module::getInstance<Timer>(Module::M_TIMER))
 
 int w_step(lua_State *)
 {
-	instance->step();
+	instance()->step();
 	return 0;
 }
 
 int w_getDelta(lua_State *L)
 {
-	lua_pushnumber(L, instance->getDelta());
+	lua_pushnumber(L, instance()->getDelta());
 	return 1;
 }
 
 int w_getFPS(lua_State *L)
 {
-	lua_pushinteger(L, instance->getFPS());
+	lua_pushinteger(L, instance()->getFPS());
 	return 1;
 }
 
 int w_getAverageDelta(lua_State *L)
 {
-	lua_pushnumber(L, instance->getAverageDelta());
+	lua_pushnumber(L, instance()->getAverageDelta());
 	return 1;
 }
 
 int w_sleep(lua_State *L)
 {
-	instance->sleep(luaL_checknumber(L, 1));
+	instance()->sleep(luaL_checknumber(L, 1));
 	return 0;
 }
 
 int w_getTime(lua_State *L)
 {
-	lua_pushnumber(L, instance->getTime());
+	lua_pushnumber(L, instance()->getTime());
 	return 1;
 }
 
@@ -83,7 +83,8 @@ static const luaL_Reg functions[] =
 
 extern "C" int luaopen_love_timer(lua_State *L)
 {
-	if (instance == 0)
+	Timer *instance = instance();
+	if (instance == nullptr)
 	{
 		luax_catchexcept(L, [&](){ instance = new love::timer::sdl::Timer(); });
 	}

+ 5 - 0
src/modules/window/Window.cpp

@@ -28,6 +28,11 @@ namespace window
 
 Window *Window::singleton = nullptr;
 
+Window::Window()
+{
+	moduleType = M_WINDOW;
+}
+
 Window::~Window()
 {
 	if (singleton == this)

+ 1 - 0
src/modules/window/Window.h

@@ -75,6 +75,7 @@ public:
 		int height;
 	};
 
+	Window();
 	virtual ~Window();
 
 	virtual bool setWindow(int width = 800, int height = 600, WindowSettings *settings = nullptr) = 0;

+ 2 - 2
src/modules/window/sdl/Window.cpp

@@ -118,7 +118,7 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
 		sdlflags |= SDL_WINDOW_ALLOW_HIGHDPI;
 #endif
 
-	graphics::Graphics *gfx = (graphics::Graphics *) Module::findInstance("love.graphics.");
+	graphics::Graphics *gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
 	if (gfx != nullptr)
 		gfx->unSetMode();
 
@@ -431,7 +431,7 @@ bool Window::setFullscreen(bool fullscreen, Window::FullscreenType fstype)
 		updateSettings(newsettings);
 
 		// Update the viewport size now instead of waiting for event polling.
-		graphics::Graphics *gfx = (graphics::Graphics *) Module::findInstance("love.graphics.");
+		graphics::Graphics *gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
 		if (gfx != nullptr)
 		{
 			int width = curMode.width;

+ 26 - 25
src/modules/window/wrap_Window.cpp

@@ -26,11 +26,11 @@ namespace love
 namespace window
 {
 
-static Window *instance = nullptr;
+#define instance() (Module::getInstance<Window>(Module::M_WINDOW))
 
 int w_getDisplayCount(lua_State *L)
 {
-	lua_pushinteger(L, instance->getDisplayCount());
+	lua_pushinteger(L, instance()->getDisplayCount());
 	return 1;
 }
 
@@ -39,7 +39,7 @@ int w_getDisplayName(lua_State *L)
 	int index = luaL_checkint(L, 1) - 1;
 
 	const char *name = nullptr;
-	luax_catchexcept(L, [&](){ name = instance->getDisplayName(index); });
+	luax_catchexcept(L, [&](){ name = instance()->getDisplayName(index); });
 
 	lua_pushstring(L, name);
 	return 1;
@@ -59,7 +59,7 @@ int w_setMode(lua_State *L)
 
 	if (lua_isnoneornil(L, 3))
 	{
-		luax_pushboolean(L, instance->setWindow(w, h, 0));
+		luax_pushboolean(L, instance()->setWindow(w, h, 0));
 		return 1;
 	}
 
@@ -117,7 +117,7 @@ int w_setMode(lua_State *L)
 	settings.display--;
 
 	luax_catchexcept(L,
-		[&](){ luax_pushboolean(L, instance->setWindow(w, h, &settings)); }
+		[&](){ luax_pushboolean(L, instance()->setWindow(w, h, &settings)); }
 	);
 
 	return 1;
@@ -127,7 +127,7 @@ int w_getMode(lua_State *L)
 {
 	int w, h;
 	WindowSettings settings;
-	instance->getWindow(w, h, settings);
+	instance()->getWindow(w, h, settings);
 	lua_pushnumber(L, w);
 	lua_pushnumber(L, h);
 
@@ -183,7 +183,7 @@ int w_getFullscreenModes(lua_State *L)
 {
 	int displayindex = luaL_optint(L, 1, 1) - 1;
 
-	std::vector<Window::WindowSize> modes = instance->getFullscreenSizes(displayindex);
+	std::vector<Window::WindowSize> modes = instance()->getFullscreenSizes(displayindex);
 
 	lua_createtable(L, modes.size(), 0);
 
@@ -219,9 +219,9 @@ int w_setFullscreen(lua_State *L)
 
 	bool success = false;
 	if (fstype == Window::FULLSCREEN_TYPE_MAX_ENUM)
-		success = instance->setFullscreen(fullscreen);
+		success = instance()->setFullscreen(fullscreen);
 	else
-		success = instance->setFullscreen(fullscreen, fstype);
+		success = instance()->setFullscreen(fullscreen, fstype);
 
 	luax_pushboolean(L, success);
 	return 1;
@@ -231,7 +231,7 @@ int w_getFullscreen(lua_State *L)
 {
 	int w, h;
 	WindowSettings settings;
-	instance->getWindow(w, h, settings);
+	instance()->getWindow(w, h, settings);
 
 	const char *typestr;
 	if (!Window::getConstant(settings.fstype, typestr))
@@ -244,26 +244,26 @@ int w_getFullscreen(lua_State *L)
 
 int w_isCreated(lua_State *L)
 {
-	luax_pushboolean(L, instance->isCreated());
+	luax_pushboolean(L, instance()->isCreated());
 	return 1;
 }
 
 int w_getWidth(lua_State *L)
 {
-	lua_pushinteger(L, instance->getWidth());
+	lua_pushinteger(L, instance()->getWidth());
 	return 1;
 }
 
 int w_getHeight(lua_State *L)
 {
-	lua_pushinteger(L, instance->getHeight());
+	lua_pushinteger(L, instance()->getHeight());
 	return 1;
 }
 
 int w_getDimensions(lua_State *L)
 {
-	lua_pushinteger(L, instance->getWidth());
-	lua_pushinteger(L, instance->getHeight());
+	lua_pushinteger(L, instance()->getWidth());
+	lua_pushinteger(L, instance()->getHeight());
 	return 2;
 }
 
@@ -271,7 +271,7 @@ int w_getDesktopDimensions(lua_State *L)
 {
 	int width = 0, height = 0;
 	int displayindex = luaL_optint(L, 1, 1) - 1;
-	instance->getDesktopDimensions(displayindex, width, height);
+	instance()->getDesktopDimensions(displayindex, width, height);
 	lua_pushinteger(L, width);
 	lua_pushinteger(L, height);
 	return 2;
@@ -280,13 +280,13 @@ int w_getDesktopDimensions(lua_State *L)
 int w_setIcon(lua_State *L)
 {
 	image::ImageData *i = luax_checktype<image::ImageData>(L, 1, "ImageData", IMAGE_IMAGE_DATA_T);
-	luax_pushboolean(L, instance->setIcon(i));
+	luax_pushboolean(L, instance()->setIcon(i));
 	return 1;
 }
 
 int w_getIcon(lua_State *L)
 {
-	image::ImageData *i = instance->getIcon();
+	image::ImageData *i = instance()->getIcon();
 	if (i)
 	{
 		i->retain();
@@ -300,43 +300,43 @@ int w_getIcon(lua_State *L)
 int w_setTitle(lua_State *L)
 {
 	std::string title = luax_checkstring(L, 1);
-	instance->setWindowTitle(title);
+	instance()->setWindowTitle(title);
 	return 0;
 }
 
 int w_getTitle(lua_State *L)
 {
-	luax_pushstring(L, instance->getWindowTitle());
+	luax_pushstring(L, instance()->getWindowTitle());
 	return 1;
 }
 
 int w_hasFocus(lua_State *L)
 {
-	luax_pushboolean(L, instance->hasFocus());
+	luax_pushboolean(L, instance()->hasFocus());
 	return 1;
 }
 
 int w_hasMouseFocus(lua_State *L)
 {
-	luax_pushboolean(L, instance->hasMouseFocus());
+	luax_pushboolean(L, instance()->hasMouseFocus());
 	return 1;
 }
 
 int w_isVisible(lua_State *L)
 {
-	luax_pushboolean(L, instance->isVisible());
+	luax_pushboolean(L, instance()->isVisible());
 	return 1;
 }
 
 int w_getPixelScale(lua_State *L)
 {
-	lua_pushnumber(L, instance->getPixelScale());
+	lua_pushnumber(L, instance()->getPixelScale());
 	return 1;
 }
 
 int w_minimize(lua_State* /*L*/)
 {
-	instance->minimize();
+	instance()->minimize();
 	return 0;
 }
 
@@ -368,6 +368,7 @@ static const luaL_Reg functions[] =
 
 extern "C" int luaopen_love_window(lua_State *L)
 {
+	Window *instance = nullptr;
 	luax_catchexcept(L, [&](){ instance = sdl::Window::createSingleton(); });
 
 	WrappedModule w;