removed unnecessary OOP stuff

This commit is contained in:
Timerix 2024-09-10 02:40:00 +05:00
parent 71eea1c0fe
commit 9eef21df1b
6 changed files with 88 additions and 134 deletions

View File

@ -7,17 +7,11 @@ Assembly::Assembly(MonoAssembly *ptr)
{ {
} }
Assembly::~Assembly(){ MonoClass* Assembly::getClass(const std::string &name_space, const std::string &name){
// Tt causes SEGFAULT. auto c = mono_class_from_name(image, name_space.c_str(), name.c_str());
// Is it even possible to unload assembly from domain? if(!c)
// mono_assembly_close(ptr); throw UsefulException(format("can't get class '%s.%s'", name_space.c_str(), name.c_str()));
} return c;
std::shared_ptr<Class> 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<Class>(ptr, name_space, name);
} }
} }

View File

@ -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>(Object& v){ return v; }
template<>
void* _valueToVoidPtr<String>(String& v){ return v; }
template<>
Object _valueFromMonoObject<Object>(MonoObject* o){
return (Object)o;
}
template<>
String _valueFromMonoObject<String>(MonoObject* o){
return (String)((void*)o);
}
}

View File

@ -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);
}
}
}

View File

@ -28,94 +28,91 @@ typedef char16_t Char;
typedef MonoString* String; typedef MonoString* String;
typedef MonoObject* Object; typedef MonoObject* Object;
typedef void Void; typedef void Void;
template<typename PrimitiveT> template<typename PrimitiveT>
MonoClass* getClass(); MonoClass* getClass();
class Method { template<typename T>
public: void* valueToVoidPtr(T& v){ return &v; }
MonoMethod* ptr; template<>
MonoMethodSignature* signature; inline void* valueToVoidPtr<Object>(Object& v){ return v; }
const std::string_view name; template<>
MonoType* return_type; inline void* valueToVoidPtr<String>(String& v){ return v; }
std::vector<MonoType*> argument_types;
Method(MonoMethod* ptr, const std::string_view& name);
};
template<typename T> template<typename T>
void* _valueToVoidPtr(T& v){ T valueFromMonoObject(MonoObject* o){
return &v;
}
template<typename T>
T _valueFromMonoObject(MonoObject* o){
void* result_value_ptr = mono_object_unbox(o); void* result_value_ptr = mono_object_unbox(o);
if(result_value_ptr == nullptr) if(result_value_ptr == nullptr)
throw UsefulException("can't unbox method value"); throw UsefulException("can't unbox method value");
return *((T*)result_value_ptr); return *((T*)result_value_ptr);
} }
template<>
inline Object valueFromMonoObject<Object>(MonoObject* o){ return o; }
template<>
inline String valueFromMonoObject<String>(MonoObject* o){ return (String)((void*)o); }
class Class { void getMethodSignatureTypes(MonoMethod* mono_method,
MonoType** return_type,
std::vector<MonoType*>& argument_types);
public: /// @brief all types must have template implementation of getClass<T>()
std::multimap<std::string_view, Method> methods; /// @tparam ReturnT return type
MonoClass* ptr; /// @tparam ...ArgTypes argument types
const std::string name_space; /// @return function which takes arguments and returns value of ReturnT
const std::string name; template<typename ReturnT, typename... ArgTypes>
std::shared_ptr<std::function<ReturnT(MonoObject*, ArgTypes...)>> getMethod(
MonoClass* target_class,
const std::string& name)
{
static MonoClass* arg_classes[] = { getClass<ArgTypes>()... };
static MonoClass* return_class = getClass<ReturnT>();
if(target_class == nullptr)
throw UsefulException("target_class is nullptr");
Class(MonoClass* ptr, const std::string& name_space, const std::string& name); // iterate each method
Class(const Class&) = delete; void* iter = nullptr;
MonoMethod* m = nullptr;
/// @brief all types must have template implementation of getClass<T>() MonoType* return_type = nullptr;
/// @tparam ReturnT return type std::vector<MonoType*> argument_types;
/// @tparam ...ArgTypes argument types while( (m = mono_class_get_methods(target_class, &iter)) ){
/// @return function which takes arguments and returns value of ReturnT argument_types.clear();
template<typename ReturnT, typename... ArgTypes> getMethodSignatureTypes(m, &return_type, argument_types);
std::shared_ptr<std::function<ReturnT(MonoObject*, ArgTypes...)>> getMethod(const std::string& name){ // compare argument count
Method* m = nullptr; if(argument_types.size() != sizeof...(ArgTypes))
static std::vector<MonoClass*> arg_classes { getClass<ArgTypes>()... }; continue;
// iterate each method overload // compare return type
for(auto it = methods.find(name); it != methods.end(); it++){ if(!mono_metadata_type_equal(return_type, mono_class_get_type(return_class)))
m = &it->second; continue;
// compare argument count // compare argument types
if(m->argument_types.size() != arg_classes.size()) bool argument_types_mismatch = false;
continue; for(size_t i = 0; i < sizeof...(ArgTypes); i++){
// compare return type if(!mono_metadata_type_equal(argument_types[i], mono_class_get_type(arg_classes[i]))){
if(!mono_metadata_type_equal(m->return_type, mono_class_get_type(getClass<ReturnT>()))) argument_types_mismatch = true;
continue; break;
// 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;
}
} }
if(argument_types_mismatch)
continue;
// passed all tests successfully
break;
} }
if(argument_types_mismatch)
// if method not found throw exception continue;
if(m == nullptr) // passed all tests successfully
throw UsefulException(format("can't get method '%s' from class '%s'", break;
name.c_str(), this->name.c_str()));
MonoMethod* m_ptr = m->ptr;
return std::make_shared<std::function<ReturnT(MonoObject*, ArgTypes...)>>(
[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<ReturnT>(result);
}
);
} }
};
// 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<std::function<ReturnT(MonoObject*, ArgTypes...)>>(
[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<ReturnT>(result);
}
);
}
class Assembly { class Assembly {
MonoAssembly* ptr; MonoAssembly* ptr;
@ -124,9 +121,8 @@ class Assembly {
public: public:
Assembly(MonoAssembly* ptr); Assembly(MonoAssembly* ptr);
Assembly(const Assembly&) = delete; Assembly(const Assembly&) = delete;
~Assembly();
std::shared_ptr<Class> 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 ///LINUX: `config.xml`, `mscorelib.dll`, `libmono-native.so` in `mono-libs` directory

View File

@ -25,4 +25,17 @@ std::shared_ptr<Assembly> RuntimeJIT::loadAssembly(const std::string &name){
return std::make_shared<Assembly>(ptr); return std::make_shared<Assembly>(ptr);
} }
void getMethodSignatureTypes(MonoMethod* mono_method,
MonoType** return_type,
std::vector<MonoType*>& 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);
}
}
} }

View File

@ -21,7 +21,7 @@ int main(int argc, const char** argv){
Mono::RuntimeJIT mono; Mono::RuntimeJIT mono;
auto a = mono.loadAssembly("app.exe"); auto a = mono.loadAssembly("app.exe");
auto c = a->getClass("", "A"); auto c = a->getClass("", "A");
auto m = c->getMethod<Mono::Int, Mono::Byte, Mono::Float>("Method"); auto m = Mono::getMethod<Mono::Int, Mono::Byte, Mono::Float>(c, "Method");
std::cout<<"method has been found"<<std::endl; std::cout<<"method has been found"<<std::endl;
Mono::Int r = m->operator()(nullptr, 16, 0.32); Mono::Int r = m->operator()(nullptr, 16, 0.32);
std::cout<<"result: "<<r<<std::endl; std::cout<<"result: "<<r<<std::endl;