diff --git a/src/native_helper.cpp b/src/native_helper.cpp new file mode 100644 index 0000000..ae39694 --- /dev/null +++ b/src/native_helper.cpp @@ -0,0 +1,151 @@ +#include "logger.h" + +#include +#include +#include +#include +#include + +FILE_LOGGER(); + + +namespace native_helper { +enum class ArgType : unsigned char { n = -1, v, ui8, ui16, ui32, ui64, i8, i16, i32, i64, f, d, p, b, c }; +template +constexpr auto cast_to_int = [] { + using enum ArgType; +#define RT_IF(T, I) \ + if constexpr (type == T) return I + RT_IF(v, 0); + RT_IF(ui8, 1); + RT_IF(ui16, 2); + RT_IF(ui32, 3); + RT_IF(ui64, 4); + RT_IF(i8, 5); + RT_IF(i16, 6); + RT_IF(i32, 7); + RT_IF(i64, 8); + RT_IF(f, 9); + RT_IF(d, 10); + RT_IF(p, 11); + RT_IF(b, 12); + RT_IF(c, 13); +#undef RT_IF +}(); + +using TypeVariant = std::variant< + std::monostate, + uint8_t, + uint16_t, + uint32_t, + uint64_t, + int8_t, + int16_t, + int32_t, + int64_t, + float, + double, + void*, + bool, + char>; + +TypeVariant call(ArgType ret, const std::vector& args, const std::vector& vals, void* fp) { + auto vm = dcNewCallVM(1024); + using enum ArgType; + // logger.info("call:{}", __LINE__); + for (int i = 0; i < std::min(args.size(), vals.size()); i++) { + switch (args[i]) { + case ui8: + dcArgChar(vm, std::get>(vals[i])); + break; + case i8: + dcArgChar(vm, std::get>(vals[i])); + break; + case ui16: + dcArgShort(vm, std::get>(vals[i])); + break; + case i16: + dcArgShort(vm, std::get>(vals[i])); + break; + case ui32: + dcArgInt(vm, std::get>(vals[i])); + break; + case i32: + dcArgInt(vm, std::get>(vals[i])); + break; + case ui64: + dcArgLongLong(vm, std::get>(vals[i])); + break; + case i64: + dcArgLongLong(vm, std::get>(vals[i])); + break; + case f: + dcArgFloat(vm, std::get>(vals[i])); + break; + case d: + dcArgDouble(vm, std::get>(vals[i])); + break; + case p: + dcArgPointer(vm, std::get>(vals[i])); + break; + case b: + dcArgBool(vm, std::get>(vals[i])); + break; + case c: + dcArgChar(vm, std::get>(vals[i])); + break; + default: + std::unreachable(); + } + } + // logger.info("call:{}", __LINE__); + TypeVariant res{}; + switch (ret) { + case v: + dcCallVoid(vm, fp); + break; + case ui8: + res.emplace>(dcCallChar(vm, fp)); + break; + case i8: + res.emplace>(dcCallChar(vm, fp)); + break; + case ui16: + res.emplace>(dcCallShort(vm, fp)); + break; + case i16: + res.emplace>(dcCallShort(vm, fp)); + break; + case ui32: + res.emplace>(dcCallInt(vm, fp)); + break; + case i32: + res.emplace>(dcCallInt(vm, fp)); + break; + case ui64: + res.emplace>(dcCallLongLong(vm, fp)); + break; + case i64: + res.emplace>(dcCallLongLong(vm, fp)); + break; + case f: + res.emplace>(dcCallFloat(vm, fp)); + break; + case d: + res.emplace>(dcCallDouble(vm, fp)); + break; + case p: + res.emplace>(dcCallPointer(vm, fp)); + break; + case b: + res.emplace>(dcCallBool(vm, fp)); + break; + case c: + res.emplace>(dcCallChar(vm, fp)); + break; + default: + std::unreachable(); + } + return res; +} +} // namespace native_helper diff --git a/src/native_helper.h b/src/native_helper.h new file mode 100644 index 0000000..38f5663 --- /dev/null +++ b/src/native_helper.h @@ -0,0 +1,68 @@ +#pragma once +#include +#include +#include +#include + + +namespace native_helper { +using TypeVariant = std::variant< + std::monostate, + uint8_t, + uint16_t, + uint32_t, + uint64_t, + int8_t, + int16_t, + int32_t, + int64_t, + float, + double, + void*, + bool, + char>; +enum class ArgType : unsigned char { n = -1, v, ui8, ui16, ui32, ui64, i8, i16, i32, i64, f, d, p, b, c }; +ArgType form_string(const auto& str) { + using enum ArgType; + using namespace std::string_view_literals; +#define RT_IF(T) \ + if (str == #T##sv) return T; + RT_IF(v); + RT_IF(ui8); + RT_IF(ui16); + RT_IF(ui32); + RT_IF(ui64); + RT_IF(i8); + RT_IF(i16); + RT_IF(i32); + RT_IF(i64); + RT_IF(f); + RT_IF(d); + RT_IF(b); + RT_IF(c); +#undef RT_IF + return n; +} +template +constexpr auto cast_to_int = [] { + using enum ArgType; +#define RT_IF(T, I) \ + if constexpr (type == T) return I + RT_IF(v, 0); + RT_IF(ui8, 1); + RT_IF(ui16, 2); + RT_IF(ui32, 3); + RT_IF(ui64, 4); + RT_IF(i8, 5); + RT_IF(i16, 6); + RT_IF(i32, 7); + RT_IF(i64, 8); + RT_IF(f, 9); + RT_IF(d, 10); + RT_IF(p, 11); + RT_IF(b, 12); + RT_IF(c, 13); +#undef RT_IF +}(); +TypeVariant call(ArgType ret, const std::vector& args, const std::vector& vals, void* fp); +} // namespace native_helper diff --git a/src/pocketpy_engine_imp.cpp b/src/pocketpy_engine_imp.cpp index 7dc8788..bb11dda 100644 --- a/src/pocketpy_engine_imp.cpp +++ b/src/pocketpy_engine_imp.cpp @@ -1,5 +1,6 @@ #include "loader_info.hpp" #include "logger.h" +#include "native_helper.h" #include "pocketpy.h" #include "pocketpy_plugin_loader.hpp" #include "pocketpy_type_binds.h" @@ -329,6 +330,125 @@ void setupHelperModule(VM* vm) { nbtSetter_context.val = v; return VAR(nbtSetter()); }); + vm->bind(helperModule, "call(symbol:str,ret:str,*args)", [](VM* vm, ArgsView args) { + std::vector<::native_helper::ArgType> argtypes; + std::vector<::native_helper::TypeVariant> argvals; + Tuple _args = _CAST(Tuple, args[2]); + for (auto arg : _args) { + Tuple tv = _CAST(Tuple, arg); + if (tv.size() != 2) { + vm->RuntimeError("arg size must be 2"); + return VAR(NoReturn{}); + } else { + auto type = ::native_helper::form_string(_CAST(Str&, tv[0]).sv()); + using enum ::native_helper::ArgType; + using namespace native_helper; + ::native_helper::TypeVariant va; + /*logger.info("call_bind:{}", __LINE__);*/ + switch (type) { +#define CASE(N) \ + case ui##N: \ + /*logger.info("call_bind:{}", __LINE__);*/ \ + va.emplace>(_CAST(uint##N##_t, tv[1])); \ + break; \ + case i##N: \ + /*logger.info("call_bind:{}", __LINE__);*/ \ + va.emplace>(_CAST(uint##N##_t, tv[1])); \ + break + case ui8: + va.emplace>(_py_cast(vm, tv[1])); + break; + case i8: + va.emplace>(_py_cast(vm, tv[1])); + break; + CASE(16); + CASE(32); + CASE(64); +#undef CASE + case f: + // logger.info("call_bind:{}", __LINE__); + va.emplace>(_CAST(float, tv[1])); + break; + case d: + // logger.info("call_bind:{}", __LINE__); + va.emplace>(_CAST(double, tv[1])); + break; + case b: + // logger.info("call_bind:{}", __LINE__); + va.emplace>(_CAST(bool, tv[1])); + break; + case c: + // logger.info("call_bind:{}", __LINE__); + va.emplace>(_CAST(char, tv[1])); + break; + default: + logger.info("call_bind:{}", __LINE__); + break; + } + logger.info("call_bind:{}", __LINE__); + argtypes.push_back(type); + argvals.push_back(va); + } + } + auto res = ::native_helper::call( + ::native_helper::form_string(_CAST(Str&, args[1]).sv()), + argtypes, + argvals, + ll::memory::resolveSymbol(_CAST(Str&, args[0]).sv(), false) + ); + using enum ::native_helper::ArgType; + using namespace ::native_helper; + switch (::native_helper::form_string(_CAST(Str&, args[1]).sv())) { + case v: + return VAR(NoReturn{}); + break; +#define RT(N) return VAR(std::get<::native_helper::cast_to_int>(res)) + case ui8: + RT(ui8); + break; + case i8: + RT(i8); + break; + case ui16: + RT(ui16); + break; + case i16: + RT(i16); + break; + case ui32: + RT(ui32); + break; + case i32: + RT(i32); + break; + case ui64: + RT(ui64); + break; + case i64: + RT(i64); + break; + case f: + RT(f); + break; + case d: + RT(d); + break; + case p: + RT(p); + break; + case b: + RT(b); + break; + case c: + RT(c); + break; + default: + vm->RuntimeError("unknown type"); + return VAR(NoReturn{}); + break; + } +#undef RT + }); } struct { ::std::string current_import_path; diff --git a/src/pocketpy_plugin_loader_imp.cpp b/src/pocketpy_plugin_loader_imp.cpp index e75d905..a9300d7 100644 --- a/src/pocketpy_plugin_loader_imp.cpp +++ b/src/pocketpy_plugin_loader_imp.cpp @@ -45,5 +45,5 @@ bool ::pocketpy_plugin_loader::pocketpy_plugin_manager::disable(std::string_view std::shared_ptr pocketpy_plugin_loader::pocketpy_plugin_manager::get(std::string_view name) { // return ::pocketpy_plugin_loader::engine::disable(name); auto manager = ::pocketpy_plugin_loader::pocketpy_plugin_manager::Impl::data(); - return manager->getPlugin(name); -} \ No newline at end of file + return manager->getPlugin(name); // +} diff --git a/src/type_wappers/Actor_wapper.h b/src/type_wappers/Actor_wapper.h index 73d7a72..db7eebc 100644 --- a/src/type_wappers/Actor_wapper.h +++ b/src/type_wappers/Actor_wapper.h @@ -205,4 +205,4 @@ struct ActorWapper { } PY_CLASS(ActorWapper, TypeWappers, ActorWapper) }; -} // namespace type_wappers +} // namespace type_wappers \ No newline at end of file