Class::getMethod
This commit is contained in:
parent
478e6049c9
commit
71eea1c0fe
23
src/Mono/Assembly.cpp
Normal file
23
src/Mono/Assembly.cpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include "Mono.hpp"
|
||||||
|
|
||||||
|
namespace Mono {
|
||||||
|
|
||||||
|
Assembly::Assembly(MonoAssembly *ptr)
|
||||||
|
: ptr(ptr), image(mono_assembly_get_image(ptr))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Assembly::~Assembly(){
|
||||||
|
// Tt causes SEGFAULT.
|
||||||
|
// Is it even possible to unload assembly from domain?
|
||||||
|
// mono_assembly_close(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
33
src/Mono/Class.cpp
Normal file
33
src/Mono/Class.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
16
src/Mono/Method.cpp
Normal file
16
src/Mono/Method.cpp
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,80 +1,22 @@
|
|||||||
#include "Mono.hpp"
|
#include "Mono.hpp"
|
||||||
#include "../UsefulException.hpp"
|
#include <mono/metadata/appdomain.h>
|
||||||
#include "../format.hpp"
|
|
||||||
#include <mono/jit/jit.h>
|
|
||||||
#include <mono/metadata/mono-config.h>
|
|
||||||
#include <mono/metadata/debug-helpers.h>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace Mono {
|
namespace Mono {
|
||||||
|
|
||||||
RuntimeJIT::RuntimeJIT(const std::string& domain_name){
|
template <> MonoClass* getClass<SByte>(){ return mono_get_sbyte_class(); }
|
||||||
mono_set_dirs("mono-libs", "mono-libs");
|
template <> MonoClass* getClass<Byte>(){ return mono_get_byte_class(); }
|
||||||
mono_set_assemblies_path("mono-libs");
|
template <> MonoClass* getClass<Short>(){ return mono_get_int16_class(); }
|
||||||
mono_config_parse("mono-libs/config.xml");
|
template <> MonoClass* getClass<UShort>(){ return mono_get_uint16_class(); }
|
||||||
|
template <> MonoClass* getClass<Int>(){ return mono_get_int32_class(); }
|
||||||
|
template <> MonoClass* getClass<UInt>(){ return mono_get_uint32_class(); }
|
||||||
|
template <> MonoClass* getClass<Long>(){ return mono_get_int64_class(); }
|
||||||
|
template <> MonoClass* getClass<ULong>(){ return mono_get_uint64_class(); }
|
||||||
|
template <> MonoClass* getClass<Float>(){ return mono_get_single_class(); }
|
||||||
|
template <> MonoClass* getClass<Double>(){ return mono_get_double_class(); }
|
||||||
|
template <> MonoClass* getClass<Bool>(){ return mono_get_boolean_class(); }
|
||||||
|
template <> MonoClass* getClass<Char>(){ return mono_get_char_class(); }
|
||||||
|
template <> MonoClass* getClass<String>(){ return mono_get_string_class(); }
|
||||||
|
template <> MonoClass* getClass<Object>(){ return mono_get_object_class(); }
|
||||||
|
template <> MonoClass* getClass<Void>(){ return mono_get_void_class(); }
|
||||||
|
|
||||||
domain = mono_jit_init(domain_name.c_str());
|
|
||||||
if(!domain)
|
|
||||||
throw UsefulException("can't initialize mono domain");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeJIT::~RuntimeJIT(){
|
|
||||||
mono_jit_cleanup(domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Assembly> RuntimeJIT::loadAssembly(const std::string &name){
|
|
||||||
MonoAssembly* ptr = mono_domain_assembly_open(domain, "app.exe");
|
|
||||||
if(!ptr)
|
|
||||||
throw UsefulException(format("can't load assembly '%s'", name.c_str()));
|
|
||||||
return std::make_shared<Assembly>(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Assembly::Assembly(MonoAssembly *ptr)
|
|
||||||
: ptr(ptr), image(mono_assembly_get_image(ptr))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Assembly::~Assembly(){
|
|
||||||
// Tt causes SEGFAULT.
|
|
||||||
// Is it even possible to unload assembly from domain?
|
|
||||||
// mono_assembly_close(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
Class::Class(MonoClass *ptr)
|
|
||||||
: ptr(ptr)
|
|
||||||
{
|
|
||||||
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(name, m));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ReturnT, typename... ArgTypes>
|
|
||||||
std::shared_ptr<std::function<ReturnT(ArgTypes...)>> getMethod(const std::string& name){
|
|
||||||
|
|
||||||
return std::make_shared<std::function<ReturnT(ArgTypes...)>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Method::Method(const std::string_view &name, MonoMethod *ptr)
|
|
||||||
: ptr(ptr), signature(mono_method_signature(ptr)), name(name)
|
|
||||||
{
|
|
||||||
void* iter = nullptr;
|
|
||||||
MonoType* rt = mono_signature_get_return_type(signature);
|
|
||||||
MonoType* pt = nullptr;
|
|
||||||
while( (pt = mono_signature_get_params(signature, &iter)) ){
|
|
||||||
std::cout<<"name: "<<mono_type_get_name(pt)<<std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Mono
|
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "../std.hpp"
|
#include "../std.hpp"
|
||||||
|
#include "../UsefulException.hpp"
|
||||||
|
#include "../format.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -16,34 +18,105 @@ typedef u8 Byte;
|
|||||||
typedef i16 Short;
|
typedef i16 Short;
|
||||||
typedef u16 UShort;
|
typedef u16 UShort;
|
||||||
typedef i32 Int;
|
typedef i32 Int;
|
||||||
typedef i32 UInt;
|
typedef u32 UInt;
|
||||||
typedef i64 Long;
|
typedef i64 Long;
|
||||||
typedef i64 ULong;
|
typedef u64 ULong;
|
||||||
typedef f32 Float;
|
typedef f32 Float;
|
||||||
typedef f64 Double;
|
typedef f64 Double;
|
||||||
|
typedef union { mono_bool wide_bool; } Bool; //USAGE: Bool t = {true};
|
||||||
|
typedef char16_t Char;
|
||||||
typedef MonoString* String;
|
typedef MonoString* String;
|
||||||
|
typedef MonoObject* Object;
|
||||||
|
typedef void Void;
|
||||||
|
template<typename PrimitiveT>
|
||||||
|
MonoClass* getClass();
|
||||||
|
|
||||||
class Method {
|
class Method {
|
||||||
|
public:
|
||||||
MonoMethod* ptr;
|
MonoMethod* ptr;
|
||||||
MonoMethodSignature* signature;
|
MonoMethodSignature* signature;
|
||||||
|
|
||||||
public:
|
|
||||||
const std::string_view name;
|
const std::string_view name;
|
||||||
Method(const std::string_view& name, MonoMethod* ptr);
|
MonoType* return_type;
|
||||||
|
std::vector<MonoType*> argument_types;
|
||||||
|
|
||||||
|
Method(MonoMethod* ptr, const std::string_view& name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void* _valueToVoidPtr(T& v){
|
||||||
|
return &v;
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
class Class {
|
class Class {
|
||||||
std::multimap<std::string_view, Method> methods;
|
|
||||||
MonoClass* ptr;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Class(MonoClass* ptr);
|
std::multimap<std::string_view, Method> 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;
|
Class(const Class&) = delete;
|
||||||
|
|
||||||
|
/// @brief all types must have template implementation of getClass<T>()
|
||||||
|
/// @tparam ReturnT return type
|
||||||
|
/// @tparam ...ArgTypes argument types
|
||||||
|
/// @return function which takes arguments and returns value of ReturnT
|
||||||
template<typename ReturnT, typename... ArgTypes>
|
template<typename ReturnT, typename... ArgTypes>
|
||||||
std::shared_ptr<std::function<ReturnT(ArgTypes...)>> getMethod(const std::string& name);
|
std::shared_ptr<std::function<ReturnT(MonoObject*, ArgTypes...)>> getMethod(const std::string& name){
|
||||||
|
Method* m = nullptr;
|
||||||
|
static std::vector<MonoClass*> arg_classes { getClass<ArgTypes>()... };
|
||||||
|
// 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<ReturnT>())))
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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<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);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Assembly {
|
class Assembly {
|
||||||
MonoAssembly* ptr;
|
MonoAssembly* ptr;
|
||||||
MonoImage* image;
|
MonoImage* image;
|
||||||
@ -69,4 +142,4 @@ public:
|
|||||||
std::shared_ptr<Assembly> loadAssembly(const std::string& name);
|
std::shared_ptr<Assembly> loadAssembly(const std::string& name);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace Mono
|
||||||
|
|||||||
28
src/Mono/Runtime.cpp
Normal file
28
src/Mono/Runtime.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include "Mono.hpp"
|
||||||
|
#include <mono/jit/jit.h>
|
||||||
|
#include <mono/metadata/mono-config.h>
|
||||||
|
|
||||||
|
namespace Mono {
|
||||||
|
|
||||||
|
RuntimeJIT::RuntimeJIT(const std::string& domain_name){
|
||||||
|
mono_set_dirs("mono-libs", "mono-libs");
|
||||||
|
mono_set_assemblies_path("mono-libs");
|
||||||
|
mono_config_parse("mono-libs/config.xml");
|
||||||
|
|
||||||
|
domain = mono_jit_init(domain_name.c_str());
|
||||||
|
if(!domain)
|
||||||
|
throw UsefulException("can't initialize mono domain");
|
||||||
|
}
|
||||||
|
|
||||||
|
RuntimeJIT::~RuntimeJIT(){
|
||||||
|
mono_jit_cleanup(domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Assembly> RuntimeJIT::loadAssembly(const std::string &name){
|
||||||
|
MonoAssembly* ptr = mono_domain_assembly_open(domain, "app.exe");
|
||||||
|
if(!ptr)
|
||||||
|
throw UsefulException(format("can't load assembly '%s'", name.c_str()));
|
||||||
|
return std::make_shared<Assembly>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
11
src/main.cpp
11
src/main.cpp
@ -15,12 +15,19 @@ void update(f64 deltaTime){
|
|||||||
|
|
||||||
int main(int argc, const char** argv){
|
int main(int argc, const char** argv){
|
||||||
try {
|
try {
|
||||||
Resources::init();
|
// Resources::init();
|
||||||
std::cout<<"initialized resource loader"<<std::endl;
|
// std::cout<<"initialized resource loader"<<std::endl;
|
||||||
|
|
||||||
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");
|
||||||
|
std::cout<<"method has been found"<<std::endl;
|
||||||
|
Mono::Int r = m->operator()(nullptr, 16, 0.32);
|
||||||
|
std::cout<<"result: "<<r<<std::endl;
|
||||||
|
return 0;
|
||||||
std::cout<<"initialized mono jit runtime"<<std::endl;
|
std::cout<<"initialized mono jit runtime"<<std::endl;
|
||||||
|
|
||||||
GUI::MainWindow w;
|
GUI::MainWindow w;
|
||||||
w.open("ougge", update);
|
w.open("ougge", update);
|
||||||
std::cout<<"created sdl window"<<std::endl;
|
std::cout<<"created sdl window"<<std::endl;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user