载入中...
搜索中...
未找到
Plugins.cpp
浏览该文件的文档.
1#include "plugins/Plugins.h"
2
3#include "common/Exception.h"
4
5#include <simplesquirrel/simplesquirrel.hpp>
6
7#if defined(_WIN32)
8# define WIN32_LEAN_AND_MEAN
9# include <windows.h>
10#else
11# include <dlfcn.h>
12#endif
13
14namespace eve::plugins {
15
16using PluginInitFn = int (*)();
17
19
20Plugins::Plugins() = default;
21
23 for (auto& kv : loaded_) {
24#if defined(_WIN32)
25 if (kv.second.native)
26 FreeLibrary(static_cast<HMODULE>(kv.second.native));
27#else
28 if (kv.second.native)
29 dlclose(kv.second.native);
30#endif
31 }
32 loaded_.clear();
33}
34
35bool Plugins::load(const std::string& path) {
36 if (path.empty())
37 throw Exception("plugins.load: empty path");
38 if (loaded_.count(path))
39 return true;
40
41#if defined(_WIN32)
42 HMODULE mod = LoadLibraryA(path.c_str());
43 if (!mod)
44 throw Exception("plugins.load: LoadLibrary failed for '%s' (err=%lu)", path.c_str(),
45 GetLastError());
46 auto init = reinterpret_cast<PluginInitFn>(GetProcAddress(mod, "eve_plugin_init"));
47 if (!init) {
48 FreeLibrary(mod);
49 throw Exception("plugins.load: missing eve_plugin_init in '%s'", path.c_str());
50 }
51 int rc = init();
52 if (rc != 0) {
53 FreeLibrary(mod);
54 throw Exception("plugins.load: eve_plugin_init returned %d for '%s'", rc, path.c_str());
55 }
56 loaded_[path] = Handle{mod, path};
57#else
58 void* mod = dlopen(path.c_str(), RTLD_NOW | RTLD_GLOBAL);
59 if (!mod)
60 throw Exception("plugins.load: dlopen failed for '%s': %s", path.c_str(), dlerror());
61 dlerror();
62 auto init = reinterpret_cast<PluginInitFn>(dlsym(mod, "eve_plugin_init"));
63 const char* err = dlerror();
64 if (err != nullptr || !init) {
65 dlclose(mod);
66 throw Exception("plugins.load: missing eve_plugin_init in '%s'%s%s", path.c_str(),
67 err ? ": " : "", err ? err : "");
68 }
69 int rc = init();
70 if (rc != 0) {
71 dlclose(mod);
72 throw Exception("plugins.load: eve_plugin_init returned %d for '%s'", rc, path.c_str());
73 }
74 loaded_[path] = Handle{mod, path};
75#endif
76
78 throw Exception("plugins.load: expose_pending failed after loading '%s'", path.c_str());
79 return true;
80}
81
82bool Plugins::unload(const std::string& path) {
83 auto it = loaded_.find(path);
84 if (it == loaded_.end())
85 return false;
86#if defined(_WIN32)
87 FreeLibrary(static_cast<HMODULE>(it->second.native));
88#else
89 dlclose(it->second.native);
90#endif
91 loaded_.erase(it);
92 return true;
93}
94
95bool Plugins::isLoaded(const std::string& path) const {
96 return loaded_.count(path) > 0;
97}
98
99void Plugins::expose(ssq::Table& table) {
100 auto cls = table.addClass(name, Plugins::create, false);
101 expose(cls);
102}
103
104void Plugins::expose(ssq::Class& cls) {
105 cls.addFunc("getName", &Plugins::getName);
106 cls.addFunc("load", &Plugins::load);
107 cls.addFunc("unload", &Plugins::unload);
108 cls.addFunc("isLoaded", &Plugins::isLoaded);
109}
110
111} // namespace eve::plugins
HSQOBJECT cls
Definition ECS.cpp:21
#define Module_IMPL(ModuleName, newExpr)
Definition Module.h:24
const char * name
Definition RockMesh.cpp:21
static int expose_pending()
Definition Module.cpp:79
virtual std::string getName() const =0
加载导出 eve_plugin_init 的原生动态库(dll / so / dylib)。
Definition Plugins.h:11
bool isLoaded(const std::string &path) const
插件是否已加载。
Definition Plugins.cpp:95
bool load(const std::string &path)
加载插件;路径可为绝对路径或游戏相对路径。
Definition Plugins.cpp:35
~Plugins() override
Definition Plugins.cpp:22
bool unload(const std::string &path)
卸载插件。
Definition Plugins.cpp:82
int(*)() PluginInitFn
Definition Plugins.cpp:16