forked from teamnwah/openmw-tes3coop
[Server] Implement Public API for Mono
This commit is contained in:
parent
6cbf6f05a1
commit
447a0ee8b2
6 changed files with 213 additions and 37 deletions
|
@ -19,11 +19,21 @@ Public::Public(ScriptFunc _public, const std::string &name, char ret_type, const
|
||||||
publics.emplace(name, this);
|
publics.emplace(name, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_LUA
|
||||||
Public::Public(ScriptFuncLua _public, lua_State *lua, const std::string &name, char ret_type, const std::string &def) : ScriptFunction(
|
Public::Public(ScriptFuncLua _public, lua_State *lua, const std::string &name, char ret_type, const std::string &def) : ScriptFunction(
|
||||||
_public, lua, ret_type, def)
|
_public, lua, ret_type, def)
|
||||||
{
|
{
|
||||||
publics.emplace(name, this);
|
publics.emplace(name, this);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_MONO
|
||||||
|
Public::Public(MonoObject *delegate, const std::string &name, char ret_type, const std::string &def) :
|
||||||
|
ScriptFunction(delegate, ret_type, def)
|
||||||
|
{
|
||||||
|
publics.emplace(name, this);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
boost::any Public::Call(const std::string &name, const std::vector<boost::any> &args)
|
boost::any Public::Call(const std::string &name, const std::vector<boost::any> &args)
|
||||||
{
|
{
|
||||||
|
@ -45,6 +55,15 @@ const std::string &Public::GetDefinition(const std::string &name)
|
||||||
return it->second->def;
|
return it->second->def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Public *Public::GetPublic(const std::string &name)
|
||||||
|
{
|
||||||
|
auto it = publics.find(name);
|
||||||
|
|
||||||
|
if (it == publics.end())
|
||||||
|
throw runtime_error("Public with name \"" + name + "\" does not exist");
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Public::IsLua(const std::string &name)
|
bool Public::IsLua(const std::string &name)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,6 +20,9 @@ private:
|
||||||
#if defined(ENABLE_LUA)
|
#if defined(ENABLE_LUA)
|
||||||
Public(ScriptFuncLua _public, lua_State *lua, const std::string &name, char ret_type, const std::string &def);
|
Public(ScriptFuncLua _public, lua_State *lua, const std::string &name, char ret_type, const std::string &def);
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(ENABLE_MONO)
|
||||||
|
Public(MonoObject *delegate, const std::string &name, char ret_type, const std::string &def);
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
|
@ -30,6 +33,8 @@ public:
|
||||||
|
|
||||||
static const std::string& GetDefinition(const std::string& name);
|
static const std::string& GetDefinition(const std::string& name);
|
||||||
|
|
||||||
|
static Public * GetPublic(const std::string& name);
|
||||||
|
|
||||||
static bool IsLua(const std::string &name);
|
static bool IsLua(const std::string &name);
|
||||||
|
|
||||||
static void DeleteAll();
|
static void DeleteAll();
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <mono/metadata/mono-debug.h>
|
#include <mono/metadata/mono-debug.h>
|
||||||
#include <Script/ScriptFunctions.hpp>
|
#include <Script/ScriptFunctions.hpp>
|
||||||
#include <Script/API/TimerAPI.hpp>
|
#include <Script/API/TimerAPI.hpp>
|
||||||
|
#include <Script/API/PublicFnAPI.hpp>
|
||||||
#include "LangMono.hpp"
|
#include "LangMono.hpp"
|
||||||
|
|
||||||
static MonoDomain *domain = nullptr; // shared domain
|
static MonoDomain *domain = nullptr; // shared domain
|
||||||
|
@ -23,15 +24,8 @@ std::string monoStringToStdString(MonoString *monoString)
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
boost::any LangMono::ObjectToAny(MonoObject *obj)
|
||||||
T unbox(MonoObject *obj)
|
|
||||||
{
|
{
|
||||||
return *(T *) mono_object_unbox(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::any monoObjectToAny(MonoObject *obj)
|
|
||||||
{
|
|
||||||
|
|
||||||
MonoClass *klass = mono_object_get_class(obj);
|
MonoClass *klass = mono_object_get_class(obj);
|
||||||
MonoType *rawType = mono_class_get_type(klass);
|
MonoType *rawType = mono_class_get_type(klass);
|
||||||
|
|
||||||
|
@ -41,29 +35,29 @@ boost::any monoObjectToAny(MonoObject *obj)
|
||||||
case MONO_TYPE_VOID:
|
case MONO_TYPE_VOID:
|
||||||
break;
|
break;
|
||||||
case MONO_TYPE_BOOLEAN:
|
case MONO_TYPE_BOOLEAN:
|
||||||
return (bool) unbox<MonoBoolean>(obj);
|
return (bool) Unbox<MonoBoolean>(obj);
|
||||||
case MONO_TYPE_CHAR:
|
case MONO_TYPE_CHAR:
|
||||||
return unbox<uint16_t>(obj);
|
return Unbox<uint16_t>(obj);
|
||||||
case MONO_TYPE_I1:
|
case MONO_TYPE_I1:
|
||||||
return unbox<int8_t>(obj);
|
return Unbox<int8_t>(obj);
|
||||||
case MONO_TYPE_U1:
|
case MONO_TYPE_U1:
|
||||||
return unbox<uint8_t>(obj);
|
return Unbox<uint8_t>(obj);
|
||||||
case MONO_TYPE_I2:
|
case MONO_TYPE_I2:
|
||||||
return unbox<int16_t>(obj);
|
return Unbox<int16_t>(obj);
|
||||||
case MONO_TYPE_U2:
|
case MONO_TYPE_U2:
|
||||||
return unbox<uint16_t>(obj);
|
return Unbox<uint16_t>(obj);
|
||||||
case MONO_TYPE_I4:
|
case MONO_TYPE_I4:
|
||||||
return unbox<int32_t>(obj);
|
return Unbox<int32_t>(obj);
|
||||||
case MONO_TYPE_U4:
|
case MONO_TYPE_U4:
|
||||||
return unbox<uint32_t>(obj);
|
return Unbox<uint32_t>(obj);
|
||||||
case MONO_TYPE_I8:
|
case MONO_TYPE_I8:
|
||||||
return unbox<int64_t>(obj);
|
return Unbox<int64_t>(obj);
|
||||||
case MONO_TYPE_U8:
|
case MONO_TYPE_U8:
|
||||||
return unbox<uint64_t>(obj);
|
return Unbox<uint64_t>(obj);
|
||||||
case MONO_TYPE_R4:
|
case MONO_TYPE_R4:
|
||||||
return unbox<float>(obj);
|
return Unbox<float>(obj);
|
||||||
case MONO_TYPE_R8:
|
case MONO_TYPE_R8:
|
||||||
return unbox<double>(obj);
|
return Unbox<double>(obj);
|
||||||
case MONO_TYPE_STRING:
|
case MONO_TYPE_STRING:
|
||||||
return monoStringToStdString((MonoString *) obj);
|
return monoStringToStdString((MonoString *) obj);
|
||||||
case MONO_TYPE_ARRAY:
|
case MONO_TYPE_ARRAY:
|
||||||
|
@ -84,7 +78,7 @@ int LangMono::CreateTimerEx(MonoObject *delegate, long msec, MonoString *monoStr
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < argsLength; ++i)
|
for (size_t i = 0; i < argsLength; ++i)
|
||||||
params[i] = monoObjectToAny(mono_array_get(monoArgs, MonoObject*, i));
|
params[i] = ObjectToAny(mono_array_get(monoArgs, MonoObject*, i));
|
||||||
|
|
||||||
char *types = mono_string_to_utf8(monoStr);
|
char *types = mono_string_to_utf8(monoStr);
|
||||||
int id = mwmp::TimerAPI::CreateTimerMono(delegate, msec, types, params);
|
int id = mwmp::TimerAPI::CreateTimerMono(delegate, msec, types, params);
|
||||||
|
@ -97,14 +91,152 @@ int LangMono::CreateTimerEx(MonoObject *delegate, long msec, MonoString *monoStr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LangMono::MakePublic(MonoObject *delegate, const char *name) noexcept
|
char GetTes3mpType(MonoType *type)
|
||||||
{
|
{
|
||||||
|
int typeId = mono_type_get_type(type);
|
||||||
|
switch (typeId)
|
||||||
|
{
|
||||||
|
case MONO_TYPE_VOID:
|
||||||
|
return 'v';
|
||||||
|
case MONO_TYPE_BOOLEAN:
|
||||||
|
return 'b';
|
||||||
|
case MONO_TYPE_CHAR:
|
||||||
|
return 'q';
|
||||||
|
case MONO_TYPE_I1:
|
||||||
|
return 'q';
|
||||||
|
case MONO_TYPE_U1:
|
||||||
|
return 'i';
|
||||||
|
case MONO_TYPE_I2:
|
||||||
|
return 'q';
|
||||||
|
case MONO_TYPE_U2:
|
||||||
|
return 'i';
|
||||||
|
case MONO_TYPE_I4:
|
||||||
|
return 'q';
|
||||||
|
case MONO_TYPE_U4:
|
||||||
|
return 'i';
|
||||||
|
case MONO_TYPE_I8:
|
||||||
|
return 'w';
|
||||||
|
case MONO_TYPE_U8:
|
||||||
|
return 'l';
|
||||||
|
case MONO_TYPE_R4:
|
||||||
|
return 'f';
|
||||||
|
case MONO_TYPE_R8:
|
||||||
|
return 'f';
|
||||||
|
case MONO_TYPE_STRING:
|
||||||
|
return 's';
|
||||||
|
}
|
||||||
|
throw std::invalid_argument("Mono: invalid type of argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoObject *LangMono::CallPublic(const char *name, MonoArray *args)
|
MonoObject *LangMono::AnyToObject(boost::any any, char ret_type)
|
||||||
{
|
{
|
||||||
return nullptr;
|
MonoObject *object;
|
||||||
|
switch (ret_type)
|
||||||
|
{
|
||||||
|
case 'i':
|
||||||
|
{
|
||||||
|
auto val = boost::any_cast<unsigned int>(any);
|
||||||
|
object = mono_object_new(mono_get_root_domain(), mono_get_uint32_class());
|
||||||
|
ObjectSetValue(object, val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'q':
|
||||||
|
{
|
||||||
|
auto val = boost::any_cast<signed int>(any);
|
||||||
|
object = mono_object_new(mono_get_root_domain(), mono_get_int32_class());
|
||||||
|
ObjectSetValue(object, val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'l':
|
||||||
|
{
|
||||||
|
auto val = boost::any_cast<unsigned long long>(any);
|
||||||
|
object = mono_object_new(mono_get_root_domain(), mono_get_uint64_class());
|
||||||
|
ObjectSetValue(object, val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'w':
|
||||||
|
{
|
||||||
|
auto val = boost::any_cast<signed long long>(any);
|
||||||
|
object = mono_object_new(mono_get_root_domain(), mono_get_int64_class());
|
||||||
|
ObjectSetValue(object, val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'f':
|
||||||
|
{
|
||||||
|
auto val = boost::any_cast<double>(any);
|
||||||
|
object = mono_object_new(mono_get_root_domain(), mono_get_double_class());
|
||||||
|
ObjectSetValue(object, val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'p':
|
||||||
|
{
|
||||||
|
auto val = boost::any_cast<void *>(any);
|
||||||
|
object = mono_object_new(mono_get_root_domain(), mono_get_intptr_class());
|
||||||
|
ObjectSetValue(object, (intptr_t) val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 's':
|
||||||
|
{
|
||||||
|
auto val = mono_string_new(mono_domain_get(), boost::any_cast<const char *>(any));
|
||||||
|
object = (MonoObject*) val;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'b':
|
||||||
|
{
|
||||||
|
auto val = boost::any_cast<int>(any);
|
||||||
|
object = mono_object_new(mono_get_root_domain(), mono_get_boolean_class());
|
||||||
|
ObjectSetValue(object, (bool) val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("Mono call: Unknown argument identifier " + ret_type);
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void LangMono::MakePublic(MonoObject *delegate, MonoString *monoName) noexcept
|
||||||
|
{
|
||||||
|
MonoClass *klass = mono_object_get_class(delegate);
|
||||||
|
MonoMethod *method = mono_get_delegate_invoke(klass);
|
||||||
|
MonoMethodSignature *signature = mono_method_signature(method);
|
||||||
|
|
||||||
|
MonoType *retType = mono_signature_get_return_type(signature);
|
||||||
|
size_t argsCnt = mono_signature_get_param_count(signature);
|
||||||
|
|
||||||
|
void *iter = nullptr;
|
||||||
|
std::vector<char> def(argsCnt + 1);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < argsCnt; ++i)
|
||||||
|
def[i] = GetTes3mpType(mono_signature_get_params(signature, &iter));
|
||||||
|
|
||||||
|
char ret_type = GetTes3mpType(retType);
|
||||||
|
char *name = mono_string_to_utf8(monoName);
|
||||||
|
Public::MakePublic(delegate, name, ret_type, def.data());
|
||||||
|
mono_free(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
MonoObject *LangMono::CallPublic(MonoString *monoFnName, MonoArray *monoArgs)
|
||||||
|
{
|
||||||
|
size_t argsLength = mono_array_length(monoArgs);
|
||||||
|
char *fnName = mono_string_to_utf8(monoFnName);
|
||||||
|
|
||||||
|
auto pPublic = Public::GetPublic(fnName);
|
||||||
|
mono_free(fnName);
|
||||||
|
|
||||||
|
if (argsLength != pPublic->def.size())
|
||||||
|
throw std::invalid_argument("Mono call: Number of arguments does not match definition");
|
||||||
|
|
||||||
|
std::vector<boost::any> params(argsLength);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < argsLength; ++i)
|
||||||
|
params[i] = ObjectToAny(mono_array_get(monoArgs, MonoObject*, i));
|
||||||
|
|
||||||
|
boost::any ret = pPublic->ScriptFunction::Call(params);
|
||||||
|
|
||||||
|
return AnyToObject(ret, pPublic->ret_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
lib_t LangMono::GetInterface()
|
lib_t LangMono::GetInterface()
|
||||||
|
|
|
@ -64,9 +64,24 @@ public:
|
||||||
virtual boost::any Call(const char *name, const char *argl, const std::vector<boost::any> &args) override;
|
virtual boost::any Call(const char *name, const char *argl, const std::vector<boost::any> &args) override;
|
||||||
|
|
||||||
static int CreateTimerEx(MonoObject *delegate, long msec, MonoString *monoStr, MonoArray *args);
|
static int CreateTimerEx(MonoObject *delegate, long msec, MonoString *monoStr, MonoArray *args);
|
||||||
static void MakePublic(MonoObject *delegate, const char *name) noexcept;
|
static void MakePublic(MonoObject *delegate, MonoString *name) noexcept;
|
||||||
static MonoObject *CallPublic(const char *name, MonoArray *args);
|
static MonoObject *CallPublic(MonoString *name, MonoArray *args);
|
||||||
|
|
||||||
static void Init();
|
static void Init();
|
||||||
static void Free();
|
static void Free();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static T Unbox(MonoObject *obj)
|
||||||
|
{
|
||||||
|
return *(T *) mono_object_unbox(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static void ObjectSetValue(MonoObject *obj, T value)
|
||||||
|
{
|
||||||
|
*(T*) mono_object_unbox(obj) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boost::any ObjectToAny(MonoObject *obj);
|
||||||
|
static MonoObject *AnyToObject(boost::any any, char ret_type);
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
#if defined (ENABLE_LUA)
|
#if defined (ENABLE_LUA)
|
||||||
#include "LangLua/LangLua.hpp"
|
#include "LangLua/LangLua.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(ENABLE_MONO)
|
||||||
|
#include "LangMono/LangMono.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -121,9 +124,11 @@ boost::any ScriptFunction::Call(const vector<boost::any> &args)
|
||||||
case 's':
|
case 's':
|
||||||
{
|
{
|
||||||
if (args.at(index).type() == typeid(std::string)) // mono to mono call
|
if (args.at(index).type() == typeid(std::string)) // mono to mono call
|
||||||
argList[index] = mono_string_new(mono_domain_get(), boost::any_cast<std::string>(args.at(index)).c_str());
|
argList[index] = mono_string_new(mono_domain_get(),
|
||||||
|
boost::any_cast<std::string>(args.at(index)).c_str());
|
||||||
else // lua to mono
|
else // lua to mono
|
||||||
argList[index] = mono_string_new(mono_domain_get(), boost::any_cast<const char *>(args.at(index)));
|
argList[index] = mono_string_new(mono_domain_get(),
|
||||||
|
boost::any_cast<const char *>(args.at(index)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'b':
|
case 'b':
|
||||||
|
@ -140,8 +145,7 @@ boost::any ScriptFunction::Call(const vector<boost::any> &args)
|
||||||
|
|
||||||
MonoObject *monoRet = mono_runtime_delegate_invoke(fMono.delegate, argList.data(), NULL);
|
MonoObject *monoRet = mono_runtime_delegate_invoke(fMono.delegate, argList.data(), NULL);
|
||||||
if (monoRet != nullptr)
|
if (monoRet != nullptr)
|
||||||
result = mono_object_unbox(monoRet); // todo cast
|
result = LangMono::ObjectToAny(monoRet);
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ protected:
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
public:
|
||||||
char ret_type;
|
char ret_type;
|
||||||
std::string def;
|
std::string def;
|
||||||
int script_type;
|
int script_type;
|
||||||
|
@ -54,6 +54,9 @@ protected:
|
||||||
SCRIPT_MONO
|
SCRIPT_MONO
|
||||||
};
|
};
|
||||||
|
|
||||||
|
boost::any Call(const std::vector<boost::any> &args);
|
||||||
|
protected:
|
||||||
|
|
||||||
ScriptFunction(ScriptFunc fCpp, char ret_type, const std::string &def);
|
ScriptFunction(ScriptFunc fCpp, char ret_type, const std::string &def);
|
||||||
#if defined (ENABLE_LUA)
|
#if defined (ENABLE_LUA)
|
||||||
ScriptFunction(const ScriptFuncLua &fPawn, lua_State *lua, char ret_type, const std::string &def);
|
ScriptFunction(const ScriptFuncLua &fPawn, lua_State *lua, char ret_type, const std::string &def);
|
||||||
|
@ -62,8 +65,6 @@ protected:
|
||||||
ScriptFunction(MonoObject *delegate, char ret_type, const std::string &def);
|
ScriptFunction(MonoObject *delegate, char ret_type, const std::string &def);
|
||||||
#endif
|
#endif
|
||||||
virtual ~ScriptFunction();
|
virtual ~ScriptFunction();
|
||||||
|
|
||||||
boost::any Call(const std::vector<boost::any> &args);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //SCRIPTFUNCTION_HPP
|
#endif //SCRIPTFUNCTION_HPP
|
||||||
|
|
Loading…
Reference in a new issue