Mono::Method
This commit is contained in:
parent
42b233e6a4
commit
71f77ce89c
@ -19,4 +19,54 @@ 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(); }
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
MonoMethod* tryGetMonoMethod(MonoClass* target_class, const std::string& name,
|
||||
MonoClass* return_class, MonoClass* arg_classes[], size_t arg_classes_size)
|
||||
{
|
||||
if(target_class == nullptr)
|
||||
throw UsefulException("target_class is nullptr");
|
||||
// iterate each method
|
||||
void* iter = nullptr;
|
||||
MonoMethod* m = nullptr;
|
||||
MonoType* return_type = nullptr;
|
||||
std::vector<MonoType*> 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() != arg_classes_size)
|
||||
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 < arg_classes_size; 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;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -3,9 +3,7 @@
|
||||
#include "../std.hpp"
|
||||
#include "../UsefulException.hpp"
|
||||
#include "../format.hpp"
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <mono/metadata/metadata.h>
|
||||
#include <mono/metadata/assembly.h>
|
||||
#include <mono/metadata/object.h>
|
||||
@ -55,61 +53,37 @@ void getMethodSignatureTypes(MonoMethod* mono_method,
|
||||
MonoType** return_type,
|
||||
std::vector<MonoType*>& argument_types);
|
||||
|
||||
/// all types must implement getClass<T>()
|
||||
/// searches for method `name` in `target_class` with return type `return_class` and argument types `arg_classes`
|
||||
/// @return found method or nullptr
|
||||
MonoMethod* tryGetMonoMethod(MonoClass* target_class, const std::string& name,
|
||||
MonoClass* return_class, MonoClass* arg_classes[], size_t arg_classes_size);
|
||||
|
||||
|
||||
template<typename SignatureT> class Method;
|
||||
template<typename ReturnT, typename... ArgTypes>
|
||||
std::shared_ptr<std::function<ReturnT(MonoObject*, ArgTypes...)>> getMethod(
|
||||
MonoClass* target_class,
|
||||
const std::string& name)
|
||||
class Method<ReturnT(ArgTypes...)>
|
||||
{
|
||||
static MonoClass* arg_classes[] = { getClass<ArgTypes>()... };
|
||||
static MonoClass* return_class = getClass<ReturnT>();
|
||||
if(target_class == nullptr)
|
||||
throw UsefulException("target_class is nullptr");
|
||||
MonoMethod* method_ptr;
|
||||
|
||||
// iterate each method
|
||||
void* iter = nullptr;
|
||||
MonoMethod* m = nullptr;
|
||||
MonoType* return_type = nullptr;
|
||||
std::vector<MonoType*> 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;
|
||||
public:
|
||||
ReturnT operator()(MonoObject* class_instance, ArgTypes... args) {
|
||||
void* arg_array[] = { valueToVoidPtr(args)..., nullptr };
|
||||
// TODO: exception catch
|
||||
// MonoException* ex = nullptr;
|
||||
MonoObject* result = mono_runtime_invoke(method_ptr, class_instance, arg_array, nullptr);
|
||||
return valueFromMonoObject<ReturnT>(result);
|
||||
};
|
||||
|
||||
/// all types must implement getClass<T>()
|
||||
Method(MonoClass* target_class, const std::string& name){
|
||||
static MonoClass* arg_classes[] { getClass<ArgTypes>()... };
|
||||
static MonoClass* return_class { getClass<ReturnT>() };
|
||||
method_ptr = tryGetMonoMethod(target_class, name, return_class, arg_classes, sizeof...(ArgTypes));
|
||||
if(method_ptr == nullptr)
|
||||
throw UsefulException(format("can't get method '%s' from class '%s'",
|
||||
name.c_str(), mono_class_get_name(target_class)));
|
||||
}
|
||||
|
||||
// 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 {
|
||||
|
||||
@ -25,17 +25,4 @@ std::shared_ptr<Assembly> RuntimeJIT::loadAssembly(const std::string &name){
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
30
src/function_shared_ptr.hpp
Normal file
30
src/function_shared_ptr.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
template <typename SignatureT>
|
||||
class function_shared_ptr;
|
||||
|
||||
template<typename ReturnT, typename... ArgTypes>
|
||||
class function_shared_ptr<ReturnT(ArgTypes...)> {
|
||||
public:
|
||||
using func_t = std::function<ReturnT(ArgTypes...)>;
|
||||
using ptr_t = std::shared_ptr<func_t>;
|
||||
protected:
|
||||
ptr_t func_ptr;
|
||||
|
||||
public:
|
||||
function_shared_ptr() = default;
|
||||
function_shared_ptr(function_shared_ptr&) = default;
|
||||
function_shared_ptr(function_shared_ptr&&) = default;
|
||||
function_shared_ptr(ptr_t& p) { func_ptr = p; }
|
||||
function_shared_ptr(ptr_t&& p) { func_ptr = p; }
|
||||
template<typename FunctionT>
|
||||
function_shared_ptr(FunctionT f){ func_ptr = std::make_shared<func_t>(f); }
|
||||
|
||||
ReturnT operator()(ArgTypes... args){ return func_ptr->operator()(args...); }
|
||||
|
||||
function_shared_ptr& operator=(function_shared_ptr&) = default;
|
||||
function_shared_ptr& operator=(function_shared_ptr&&) = default;
|
||||
};
|
||||
14
src/main.cpp
14
src/main.cpp
@ -21,18 +21,18 @@ int main(int argc, const char** argv){
|
||||
Mono::RuntimeJIT mono;
|
||||
auto a = mono.loadAssembly("app.exe");
|
||||
auto c = a->getClass("", "A");
|
||||
auto m = Mono::getMethod<Mono::Int, Mono::Byte, Mono::Float>(c, "Method");
|
||||
auto m = Mono::Method<Mono::Int(Mono::Byte, Mono::Float)>(c, "Method");
|
||||
std::cout<<"method has been found"<<std::endl;
|
||||
Mono::Int r = m->operator()(nullptr, 16, 0.32);
|
||||
Mono::Int r = m(nullptr, 16, 0.32);
|
||||
std::cout<<"result: "<<r<<std::endl;
|
||||
return 0;
|
||||
std::cout<<"initialized mono jit runtime"<<std::endl;
|
||||
|
||||
GUI::MainWindow w;
|
||||
w.open("ougge", update);
|
||||
std::cout<<"created sdl window"<<std::endl;
|
||||
w.startUpdateLoop();
|
||||
std::cout<<"sdl window has been cosed"<<std::endl;
|
||||
// GUI::MainWindow w;
|
||||
// w.open("ougge", update);
|
||||
// std::cout<<"created sdl window"<<std::endl;
|
||||
// w.startUpdateLoop();
|
||||
// std::cout<<"sdl window has been cosed"<<std::endl;
|
||||
}
|
||||
catch(const std::exception& e){
|
||||
std::cerr<<"Catched exception: "<<e.what()<<std::endl;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user