diff --git a/src/Mono/Assembly.cpp b/src/Mono/Assembly.cpp index 9a5cb8a..69232bf 100644 --- a/src/Mono/Assembly.cpp +++ b/src/Mono/Assembly.cpp @@ -7,17 +7,11 @@ Assembly::Assembly(MonoAssembly *ptr) { } -Assembly::~Assembly(){ - // Tt causes SEGFAULT. - // Is it even possible to unload assembly from domain? - // mono_assembly_close(ptr); -} - -std::shared_ptr Assembly::getClass(const std::string &name_space, const std::string &name){ - MonoClass* ptr = mono_class_from_name(image, name_space.c_str(), name.c_str()); - if(!ptr) - throw UsefulException(format("can't find class '%s.%s'", name_space.c_str(), name.c_str())); - return std::make_shared(ptr, name_space, name); +MonoClass* Assembly::getClass(const std::string &name_space, const std::string &name){ + auto c = mono_class_from_name(image, name_space.c_str(), name.c_str()); + if(!c) + throw UsefulException(format("can't get class '%s.%s'", name_space.c_str(), name.c_str())); + return c; } } diff --git a/src/Mono/Class.cpp b/src/Mono/Class.cpp deleted file mode 100644 index e2225cc..0000000 --- a/src/Mono/Class.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "Mono.hpp" - -namespace Mono { - -Class::Class(MonoClass *ptr, const std::string& name_space, const std::string& name) - : ptr(ptr), name_space(name_space), name(name) -{ - void* iter = nullptr; - MonoMethod* m = nullptr; - while( (m = mono_class_get_methods(ptr, &iter)) ){ - auto name = std::string_view(mono_method_get_name(m)); - methods.emplace(std::piecewise_construct, - std::forward_as_tuple(name), - std::forward_as_tuple(m, name)); - } -} - - -template<> -void* _valueToVoidPtr(Object& v){ return v; } -template<> -void* _valueToVoidPtr(String& v){ return v; } - -template<> -Object _valueFromMonoObject(MonoObject* o){ - return (Object)o; -} -template<> -String _valueFromMonoObject(MonoObject* o){ - return (String)((void*)o); -} - -} diff --git a/src/Mono/Method.cpp b/src/Mono/Method.cpp deleted file mode 100644 index d55714c..0000000 --- a/src/Mono/Method.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "Mono.hpp" - -namespace Mono { - -Method::Method(MonoMethod *ptr, const std::string_view& name) - : ptr(ptr), signature(mono_method_signature(ptr)), name(name) -{ - void* iter = nullptr; - return_type = mono_signature_get_return_type(signature); - MonoType* pt = nullptr; - while( (pt = mono_signature_get_params(signature, &iter)) ){ - argument_types.push_back(pt); - } -} - -} diff --git a/src/Mono/Mono.hpp b/src/Mono/Mono.hpp index 44f01c2..d457d1e 100644 --- a/src/Mono/Mono.hpp +++ b/src/Mono/Mono.hpp @@ -28,94 +28,91 @@ typedef char16_t Char; typedef MonoString* String; typedef MonoObject* Object; typedef void Void; + template MonoClass* getClass(); -class Method { -public: - MonoMethod* ptr; - MonoMethodSignature* signature; - const std::string_view name; - MonoType* return_type; - std::vector argument_types; - - Method(MonoMethod* ptr, const std::string_view& name); -}; - +template +void* valueToVoidPtr(T& v){ return &v; } +template<> +inline void* valueToVoidPtr(Object& v){ return v; } +template<> +inline void* valueToVoidPtr(String& v){ return v; } template -void* _valueToVoidPtr(T& v){ - return &v; -} -template -T _valueFromMonoObject(MonoObject* o){ +T valueFromMonoObject(MonoObject* o){ void* result_value_ptr = mono_object_unbox(o); if(result_value_ptr == nullptr) throw UsefulException("can't unbox method value"); return *((T*)result_value_ptr); } +template<> +inline Object valueFromMonoObject(MonoObject* o){ return o; } +template<> +inline String valueFromMonoObject(MonoObject* o){ return (String)((void*)o); } -class Class { +void getMethodSignatureTypes(MonoMethod* mono_method, + MonoType** return_type, + std::vector& argument_types); -public: - std::multimap methods; - MonoClass* ptr; - const std::string name_space; - const std::string name; - - Class(MonoClass* ptr, const std::string& name_space, const std::string& name); - Class(const Class&) = delete; +/// @brief all types must have template implementation of getClass() +/// @tparam ReturnT return type +/// @tparam ...ArgTypes argument types +/// @return function which takes arguments and returns value of ReturnT +template +std::shared_ptr> getMethod( + MonoClass* target_class, + const std::string& name) +{ + static MonoClass* arg_classes[] = { getClass()... }; + static MonoClass* return_class = getClass(); + if(target_class == nullptr) + throw UsefulException("target_class is nullptr"); - /// @brief all types must have template implementation of getClass() - /// @tparam ReturnT return type - /// @tparam ...ArgTypes argument types - /// @return function which takes arguments and returns value of ReturnT - template - std::shared_ptr> getMethod(const std::string& name){ - Method* m = nullptr; - static std::vector arg_classes { getClass()... }; - // iterate each method overload - for(auto it = methods.find(name); it != methods.end(); it++){ - m = &it->second; - // compare argument count - if(m->argument_types.size() != arg_classes.size()) - continue; - // compare return type - if(!mono_metadata_type_equal(m->return_type, mono_class_get_type(getClass()))) - continue; - // compare argument types - bool argument_types_mismatch = false; - for(size_t i = 0; i < arg_classes.size(); i++){ - if(!mono_metadata_type_equal(m->argument_types[i], mono_class_get_type(arg_classes[i]))){ - argument_types_mismatch = true; - break; - } + // iterate each method + void* iter = nullptr; + MonoMethod* m = nullptr; + MonoType* return_type = nullptr; + std::vector argument_types; + while( (m = mono_class_get_methods(target_class, &iter)) ){ + argument_types.clear(); + getMethodSignatureTypes(m, &return_type, argument_types); + // compare argument count + if(argument_types.size() != sizeof...(ArgTypes)) + continue; + // compare return type + if(!mono_metadata_type_equal(return_type, mono_class_get_type(return_class))) + continue; + // compare argument types + bool argument_types_mismatch = false; + for(size_t i = 0; i < sizeof...(ArgTypes); i++){ + if(!mono_metadata_type_equal(argument_types[i], mono_class_get_type(arg_classes[i]))){ + argument_types_mismatch = true; + break; } - if(argument_types_mismatch) - continue; - // passed all tests successfully - break; } - - // if method not found throw exception - if(m == nullptr) - throw UsefulException(format("can't get method '%s' from class '%s'", - name.c_str(), this->name.c_str())); - - MonoMethod* m_ptr = m->ptr; - return std::make_shared>( - [m_ptr](MonoObject* class_instance, ArgTypes... args) -> ReturnT - { - void* arg_array[] = { _valueToVoidPtr(args)..., nullptr }; - // MonoException* ex = nullptr; - // TODO: exception catch - MonoObject* result = mono_runtime_invoke(m_ptr, class_instance, arg_array, nullptr); - return _valueFromMonoObject(result); - } - ); + if(argument_types_mismatch) + continue; + // passed all tests successfully + break; } -}; + // if method not found throw exception + if(m == nullptr) + throw UsefulException(format("can't get method '%s' from class '%s'", + name.c_str(), mono_class_get_name(target_class))); + + return std::make_shared>( + [m](MonoObject* class_instance, ArgTypes... args) -> ReturnT + { + void* arg_array[] = { valueToVoidPtr(args)..., nullptr }; + // MonoException* ex = nullptr; + // TODO: exception catch + MonoObject* result = mono_runtime_invoke(m, class_instance, arg_array, nullptr); + return valueFromMonoObject(result); + } + ); +} class Assembly { MonoAssembly* ptr; @@ -124,9 +121,8 @@ class Assembly { public: Assembly(MonoAssembly* ptr); Assembly(const Assembly&) = delete; - ~Assembly(); - std::shared_ptr getClass(const std::string& name_space, const std::string& name); + MonoClass* getClass(const std::string& name_space, const std::string& name); }; ///LINUX: `config.xml`, `mscorelib.dll`, `libmono-native.so` in `mono-libs` directory diff --git a/src/Mono/Runtime.cpp b/src/Mono/Runtime.cpp index a85ebdf..2a070eb 100644 --- a/src/Mono/Runtime.cpp +++ b/src/Mono/Runtime.cpp @@ -25,4 +25,17 @@ std::shared_ptr RuntimeJIT::loadAssembly(const std::string &name){ return std::make_shared(ptr); } +void getMethodSignatureTypes(MonoMethod* mono_method, + MonoType** return_type, + std::vector& argument_types) +{ + auto signature = mono_method_signature(mono_method); + void* iter = nullptr; + *return_type = mono_signature_get_return_type(signature); + MonoType* pt = nullptr; + while( (pt = mono_signature_get_params(signature, &iter)) ){ + argument_types.push_back(pt); + } +} + } diff --git a/src/main.cpp b/src/main.cpp index a69f8e8..edf6d87 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,7 +21,7 @@ int main(int argc, const char** argv){ Mono::RuntimeJIT mono; auto a = mono.loadAssembly("app.exe"); auto c = a->getClass("", "A"); - auto m = c->getMethod("Method"); + auto m = Mono::getMethod(c, "Method"); std::cout<<"method has been found"<operator()(nullptr, 16, 0.32); std::cout<<"result: "<