ed21658256
CSharpParamDefaultValueMetas.cs和ubtplugin.csproj和declarationGenerator.cpp和PropertyTranslator.cpp对UserDefinedStruct.h的引用
602 lines
20 KiB
C++
602 lines
20 KiB
C++
/*
|
|
* Tencent is pleased to support the open source community by making Puerts available.
|
|
* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
|
|
* Puerts is licensed under the BSD 3-Clause License, except for the third-party components listed in the file 'LICENSE' which may
|
|
* be subject to their corresponding license terms. This file is subject to the terms and conditions defined in file 'LICENSE',
|
|
* which is part of this source code package.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <type_traits>
|
|
#include <string>
|
|
#include <cstring>
|
|
#include <functional>
|
|
#include <vector>
|
|
#include "pesapi.h"
|
|
#include "TypeInfo.hpp"
|
|
|
|
#define __DefObjectType_pesapi_impl(CLS) \
|
|
namespace PUERTS_NAMESPACE \
|
|
{ \
|
|
template <> \
|
|
struct is_objecttype<CLS> : public std::true_type \
|
|
{ \
|
|
}; \
|
|
}
|
|
|
|
#define __DefCDataPointerConverter_pesapi_impl(CLS) \
|
|
namespace PUERTS_NAMESPACE \
|
|
{ \
|
|
namespace pesapi_impl \
|
|
{ \
|
|
template <> \
|
|
struct Converter<CLS*> \
|
|
{ \
|
|
static pesapi_value toScript(pesapi_env env, CLS* value) \
|
|
{ \
|
|
return pesapi_native_object_to_value(env, DynamicTypeId<CLS>::get(value), value, false); \
|
|
} \
|
|
static CLS* toCpp(pesapi_env env, pesapi_value value) \
|
|
{ \
|
|
return static_cast<CLS*>(pesapi_get_native_object_ptr(env, value)); \
|
|
} \
|
|
static bool accept(pesapi_env env, pesapi_value value) \
|
|
{ \
|
|
return pesapi_is_instance_of(env, StaticTypeId<CLS>::get(), value); \
|
|
} \
|
|
}; \
|
|
} \
|
|
}
|
|
|
|
#define __DefCDataConverter_pesapi_impl(CLS) \
|
|
namespace PUERTS_NAMESPACE \
|
|
{ \
|
|
namespace pesapi_impl \
|
|
{ \
|
|
template <> \
|
|
struct Converter<CLS> \
|
|
{ \
|
|
static pesapi_value toScript(pesapi_env env, CLS value) \
|
|
{ \
|
|
return pesapi_native_object_to_value(env, DynamicTypeId<CLS>::get(&value), new CLS(value), true); \
|
|
} \
|
|
static CLS toCpp(pesapi_env env, pesapi_value value) \
|
|
{ \
|
|
return *static_cast<CLS*>(pesapi_get_native_object_ptr(env, value)); \
|
|
} \
|
|
static bool accept(pesapi_env env, pesapi_value value) \
|
|
{ \
|
|
return pesapi_is_instance_of(env, StaticTypeId<CLS>::get(), value); \
|
|
} \
|
|
}; \
|
|
} \
|
|
}
|
|
|
|
namespace PUERTS_NAMESPACE
|
|
{
|
|
namespace pesapi_impl
|
|
{
|
|
template <typename T, typename Enable = void>
|
|
struct Converter;
|
|
|
|
template <typename T, typename = void>
|
|
struct CustomArgumentBufferType
|
|
{
|
|
static constexpr bool enable = false;
|
|
};
|
|
|
|
struct API
|
|
{
|
|
typedef pesapi_callback_info CallbackInfoType;
|
|
typedef pesapi_env ContextType;
|
|
typedef pesapi_value ValueType;
|
|
typedef void (*FunctionCallbackType)(pesapi_callback_info info);
|
|
typedef void* (*InitializeFuncType)(pesapi_callback_info Info);
|
|
struct GeneralFunctionInfo
|
|
{
|
|
const char* Name;
|
|
FunctionCallbackType Callback;
|
|
void* Data = nullptr;
|
|
const CFunctionInfo* ReflectionInfo = nullptr;
|
|
};
|
|
|
|
struct GeneralPropertyInfo
|
|
{
|
|
const char* Name;
|
|
FunctionCallbackType Getter;
|
|
FunctionCallbackType Setter;
|
|
void* Data = nullptr;
|
|
};
|
|
|
|
typedef NamedFunctionInfo GeneralFunctionReflectionInfo;
|
|
typedef NamedPropertyInfo GeneralPropertyReflectionInfo;
|
|
|
|
inline static int GetArgsLen(pesapi_callback_info info)
|
|
{
|
|
return pesapi_get_args_len(info);
|
|
}
|
|
|
|
inline static pesapi_value GetArg(pesapi_callback_info info, int index)
|
|
{
|
|
return pesapi_get_arg(info, index);
|
|
}
|
|
|
|
inline static pesapi_env GetContext(pesapi_callback_info info)
|
|
{
|
|
return pesapi_get_env(info);
|
|
}
|
|
inline static pesapi_value GetThis(pesapi_callback_info info)
|
|
{
|
|
return pesapi_get_this(info);
|
|
}
|
|
|
|
inline static pesapi_value GetHolder(pesapi_callback_info info)
|
|
{
|
|
return pesapi_get_holder(info);
|
|
}
|
|
|
|
// use where GetSelfFromData is true
|
|
inline static void* GetFunctionData(pesapi_callback_info info)
|
|
{
|
|
return pesapi_get_userdata(info);
|
|
}
|
|
|
|
inline static void ThrowException(pesapi_callback_info info, const char* msg)
|
|
{
|
|
pesapi_throw_by_string(info, msg);
|
|
}
|
|
|
|
inline static void SetReturn(pesapi_callback_info info, pesapi_value value)
|
|
{
|
|
pesapi_add_return(info, value);
|
|
}
|
|
|
|
template <typename T1, typename T2>
|
|
inline static void LinkOuter(pesapi_env env, pesapi_value outer, pesapi_value inner)
|
|
{
|
|
pesapi_set_property_uint32(env, inner, 0, outer);
|
|
}
|
|
|
|
inline static void UpdateRefValue(pesapi_env env, pesapi_value holder, pesapi_value value)
|
|
{
|
|
if (pesapi_is_object(env, holder))
|
|
{
|
|
pesapi_update_boxed_value(env, holder, value);
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
inline static T* FastGetNativeObjectPointer(pesapi_env env, pesapi_value value)
|
|
{
|
|
return static_cast<T*>(pesapi_get_native_object_ptr(env, value));
|
|
}
|
|
|
|
inline static pesapi_value GetUndefined(pesapi_env env)
|
|
{
|
|
return pesapi_create_undefined(env);
|
|
}
|
|
|
|
inline static bool IsNullOrUndefined(pesapi_env env, pesapi_value val)
|
|
{
|
|
return pesapi_is_null(env, val) || pesapi_is_undefined(env, val);
|
|
}
|
|
|
|
typedef void (*FinalizeFuncType)(void* Ptr);
|
|
|
|
template <typename T, typename CDB>
|
|
static void Register(FinalizeFuncType Finalize, const CDB& Cdb)
|
|
{
|
|
size_t properties_count = Cdb.functions_.size() + Cdb.methods_.size() + Cdb.properties_.size() + Cdb.variables_.size();
|
|
auto properties = pesapi_alloc_property_descriptors(properties_count);
|
|
size_t pos = 0;
|
|
for (const auto& func : Cdb.functions_)
|
|
{
|
|
pesapi_set_method_info(properties, pos++, func.Name, true, func.Callback, nullptr, nullptr);
|
|
}
|
|
|
|
for (const auto& method : Cdb.methods_)
|
|
{
|
|
pesapi_set_method_info(properties, pos++, method.Name, false, method.Callback, nullptr, nullptr);
|
|
}
|
|
|
|
for (const auto& prop : Cdb.properties_)
|
|
{
|
|
pesapi_set_property_info(properties, pos++, prop.Name, false, prop.Getter, prop.Setter, nullptr, nullptr, nullptr);
|
|
}
|
|
|
|
for (const auto& prop : Cdb.variables_)
|
|
{
|
|
pesapi_set_property_info(properties, pos++, prop.Name, true, prop.Getter, prop.Setter, nullptr, nullptr, nullptr);
|
|
}
|
|
|
|
pesapi_finalize finalize = Finalize;
|
|
pesapi_define_class(StaticTypeId<T>::get(), Cdb.superTypeId_, Cdb.className_,
|
|
reinterpret_cast<InitializeFuncType>(Cdb.constructor_), finalize, properties_count, properties, nullptr);
|
|
|
|
static std::vector<NamedFunctionInfo> s_constructorInfos_{};
|
|
static std::vector<NamedFunctionInfo> s_methodInfos_{};
|
|
static std::vector<NamedFunctionInfo> s_functionInfos_{};
|
|
static std::vector<NamedPropertyInfo> s_propertyInfos_{};
|
|
static std::vector<NamedPropertyInfo> s_variableInfos_{};
|
|
|
|
s_constructorInfos_ = std::move(Cdb.constructorInfos_);
|
|
s_constructorInfos_.push_back(NamedFunctionInfo{nullptr, nullptr});
|
|
|
|
s_methodInfos_ = std::move(Cdb.methodInfos_);
|
|
s_methodInfos_.push_back(NamedFunctionInfo{nullptr, nullptr});
|
|
|
|
s_functionInfos_ = std::move(Cdb.functionInfos_);
|
|
s_functionInfos_.push_back(NamedFunctionInfo{nullptr, nullptr});
|
|
|
|
s_propertyInfos_ = std::move(Cdb.propertyInfos_);
|
|
s_propertyInfos_.push_back(NamedPropertyInfo{nullptr, nullptr});
|
|
|
|
s_variableInfos_ = std::move(Cdb.variableInfos_);
|
|
s_variableInfos_.push_back(NamedPropertyInfo{nullptr, nullptr});
|
|
|
|
pesapi_class_type_info(PUERTS_BINDING_PROTO_ID(), StaticTypeId<T>::get(), s_constructorInfos_.data(), s_methodInfos_.data(),
|
|
s_functionInfos_.data(), s_propertyInfos_.data(), s_variableInfos_.data());
|
|
}
|
|
|
|
template <typename T>
|
|
using Converter = Converter<T>;
|
|
|
|
template <typename T>
|
|
using CustomArgumentBufferType = CustomArgumentBufferType<T>;
|
|
};
|
|
|
|
class StringHolder
|
|
{
|
|
public:
|
|
StringHolder(pesapi_env env, pesapi_value value)
|
|
{
|
|
if (!value)
|
|
return;
|
|
if (pesapi_is_binary(env, value))
|
|
{
|
|
needFree_ = false;
|
|
size_t length = 0;
|
|
str_ = (char*) pesapi_get_value_binary(env, value, &length);
|
|
}
|
|
else
|
|
{
|
|
size_t length = 0;
|
|
str_ = (char*) pesapi_get_value_string_utf8(env, value, nullptr, &length);
|
|
needFree_ = false;
|
|
if (!str_)
|
|
{
|
|
str_ = new char[length + 1];
|
|
pesapi_get_value_string_utf8(env, value, str_, &length);
|
|
needFree_ = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Disallow copying and assigning.
|
|
StringHolder(const StringHolder&) = delete;
|
|
void operator=(const StringHolder&) = delete;
|
|
|
|
~StringHolder()
|
|
{
|
|
if (needFree_ && str_)
|
|
{
|
|
delete[] str_;
|
|
}
|
|
}
|
|
|
|
const char* Data() const
|
|
{
|
|
return str_;
|
|
}
|
|
|
|
private:
|
|
char* str_;
|
|
|
|
bool needFree_;
|
|
};
|
|
|
|
template <>
|
|
struct CustomArgumentBufferType<const char*>
|
|
{
|
|
using type = StringHolder;
|
|
static constexpr bool enable = true;
|
|
};
|
|
|
|
template <typename T>
|
|
struct Converter<T, typename std::enable_if<std::is_integral<T>::value && sizeof(T) == 8 && std::is_signed<T>::value>::type>
|
|
{
|
|
static pesapi_value toScript(pesapi_env env, T value)
|
|
{
|
|
return pesapi_create_int64(env, value);
|
|
}
|
|
|
|
static T toCpp(pesapi_env env, pesapi_value value)
|
|
{
|
|
return static_cast<T>(pesapi_get_value_int64(env, value));
|
|
}
|
|
|
|
static bool accept(pesapi_env env, pesapi_value value)
|
|
{
|
|
return pesapi_is_int64(env, value);
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
struct Converter<T, typename std::enable_if<std::is_integral<T>::value && sizeof(T) == 8 && !std::is_signed<T>::value>::type>
|
|
{
|
|
static pesapi_value toScript(pesapi_env env, T value)
|
|
{
|
|
return pesapi_create_uint64(env, value);
|
|
}
|
|
|
|
static T toCpp(pesapi_env env, pesapi_value value)
|
|
{
|
|
return static_cast<T>(pesapi_get_value_uint64(env, value));
|
|
}
|
|
|
|
static bool accept(pesapi_env env, pesapi_value value)
|
|
{
|
|
return pesapi_is_uint64(env, value);
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
struct Converter<T, typename std::enable_if<std::is_integral<T>::value && sizeof(T) < 8 && std::is_signed<T>::value>::type>
|
|
{
|
|
static pesapi_value toScript(pesapi_env env, T value)
|
|
{
|
|
return pesapi_create_int32(env, value);
|
|
}
|
|
|
|
static T toCpp(pesapi_env env, pesapi_value value)
|
|
{
|
|
return static_cast<T>(pesapi_get_value_int32(env, value));
|
|
}
|
|
|
|
static bool accept(pesapi_env env, pesapi_value value)
|
|
{
|
|
return pesapi_is_int32(env, value);
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
struct Converter<T, typename std::enable_if<std::is_integral<T>::value && sizeof(T) < 8 && !std::is_signed<T>::value>::type>
|
|
{
|
|
static pesapi_value toScript(pesapi_env env, T value)
|
|
{
|
|
return pesapi_create_uint32(env, value);
|
|
}
|
|
|
|
static T toCpp(pesapi_env env, pesapi_value value)
|
|
{
|
|
return static_cast<T>(pesapi_get_value_uint32(env, value));
|
|
}
|
|
|
|
static bool accept(pesapi_env env, pesapi_value value)
|
|
{
|
|
return pesapi_is_uint32(env, value);
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
struct Converter<T, typename std::enable_if<std::is_enum<T>::value>::type>
|
|
{
|
|
static pesapi_value toScript(pesapi_env env, T value)
|
|
{
|
|
return pesapi_create_int32(env, static_cast<int>(value));
|
|
}
|
|
|
|
static T toCpp(pesapi_env env, pesapi_value value)
|
|
{
|
|
return static_cast<T>(pesapi_get_value_int32(env, value));
|
|
}
|
|
|
|
static bool accept(pesapi_env env, pesapi_value value)
|
|
{
|
|
return pesapi_is_int32(env, value);
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
struct Converter<T, typename std::enable_if<std::is_floating_point<T>::value>::type>
|
|
{
|
|
static pesapi_value toScript(pesapi_env env, T value)
|
|
{
|
|
return pesapi_create_double(env, value);
|
|
}
|
|
|
|
static T toCpp(pesapi_env env, pesapi_value value)
|
|
{
|
|
return static_cast<T>(pesapi_get_value_double(env, value));
|
|
}
|
|
|
|
static bool accept(pesapi_env env, pesapi_value value)
|
|
{
|
|
return pesapi_is_double(env, value);
|
|
}
|
|
};
|
|
|
|
template <>
|
|
struct Converter<std::string>
|
|
{
|
|
static pesapi_value toScript(pesapi_env env, std::string value)
|
|
{
|
|
return pesapi_create_string_utf8(env, value.c_str(), value.size());
|
|
}
|
|
|
|
static std::string toCpp(pesapi_env env, pesapi_value value)
|
|
{
|
|
size_t bufSize = 0;
|
|
const char* str = pesapi_get_value_string_utf8(env, value, nullptr, &bufSize);
|
|
if (str)
|
|
{
|
|
return std::string(str);
|
|
}
|
|
else
|
|
{
|
|
std::vector<char> buffer(bufSize + 1);
|
|
str = pesapi_get_value_string_utf8(env, value, buffer.data(), &bufSize);
|
|
return std::string(str);
|
|
}
|
|
}
|
|
|
|
static bool accept(pesapi_env env, pesapi_value value)
|
|
{
|
|
return pesapi_is_string(env, value);
|
|
}
|
|
};
|
|
|
|
template <>
|
|
struct Converter<const char*>
|
|
{
|
|
static pesapi_value toScript(pesapi_env env, const char* value)
|
|
{
|
|
return pesapi_create_string_utf8(env, value, strlen(value));
|
|
}
|
|
|
|
static bool accept(pesapi_env env, pesapi_value value)
|
|
{
|
|
return pesapi_is_string(env, value);
|
|
}
|
|
};
|
|
|
|
template <>
|
|
struct Converter<void*>
|
|
{
|
|
static pesapi_value toScript(pesapi_env env, void* value)
|
|
{
|
|
return pesapi_create_binary(env, value, 0);
|
|
}
|
|
|
|
static void* toCpp(pesapi_env env, pesapi_value value)
|
|
{
|
|
size_t bufsize;
|
|
return pesapi_get_value_binary(env, value, &bufsize);
|
|
}
|
|
|
|
static bool accept(pesapi_env env, pesapi_value value)
|
|
{
|
|
return pesapi_is_binary(env, value);
|
|
}
|
|
};
|
|
|
|
template <>
|
|
struct Converter<bool>
|
|
{
|
|
static pesapi_value toScript(pesapi_env env, bool value)
|
|
{
|
|
return pesapi_create_boolean(env, value);
|
|
}
|
|
|
|
static bool toCpp(pesapi_env env, pesapi_value value)
|
|
{
|
|
return pesapi_get_value_bool(env, value);
|
|
}
|
|
|
|
static bool accept(pesapi_env env, pesapi_value value)
|
|
{
|
|
return pesapi_is_boolean(env, value);
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
struct Converter<std::reference_wrapper<T>, typename std::enable_if<!is_objecttype<T>::value>::type>
|
|
{
|
|
static pesapi_value toScript(pesapi_env env, const T& value)
|
|
{
|
|
return pesapi_boxing(env, Converter<T>::toScript(env, value));
|
|
}
|
|
|
|
static T toCpp(pesapi_env env, pesapi_value value)
|
|
{
|
|
return Converter<T>::toCpp(env, pesapi_unboxing(env, value));
|
|
}
|
|
|
|
static bool accept(pesapi_env env, pesapi_value value)
|
|
{
|
|
return pesapi_is_boxed_value(env, value); // do not checked inner
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
struct Converter<std::reference_wrapper<T>, typename std::enable_if<is_objecttype<T>::value>::type>
|
|
{
|
|
static pesapi_value toScript(pesapi_env env, const T& value)
|
|
{
|
|
return pesapi_boxing(env, Converter<T>::toScript(env, value));
|
|
}
|
|
|
|
static T* toCpp(pesapi_env env, pesapi_value value)
|
|
{
|
|
if (pesapi_is_object(env, value))
|
|
{
|
|
return Converter<T*>::toCpp(env, pesapi_unboxing(env, value));
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
static bool accept(pesapi_env env, pesapi_value value)
|
|
{
|
|
return pesapi_is_boxed_value(env, value); // do not checked inner
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
struct Converter<T,
|
|
typename std::enable_if<is_script_type<typename std::remove_pointer<T>::type>::value && !std::is_array<T>::value &&
|
|
!std::is_const<typename std::remove_pointer<T>::type>::value && std::is_pointer<T>::value>::type>
|
|
{
|
|
static pesapi_value toScript(pesapi_env env, T value)
|
|
{
|
|
return pesapi_create_binary(env, value, 0);
|
|
}
|
|
|
|
static T toCpp(pesapi_env env, pesapi_value value)
|
|
{
|
|
size_t bufsize;
|
|
return static_cast<T>(pesapi_get_value_binary(env, value, &bufsize));
|
|
}
|
|
|
|
static bool accept(pesapi_env env, pesapi_value value)
|
|
{
|
|
return pesapi_is_binary(env, value);
|
|
}
|
|
};
|
|
|
|
template <typename T, std::size_t Size>
|
|
struct Converter<T[Size], typename std::enable_if<is_script_type<T>::value && !std::is_const<T>::value>::type>
|
|
{
|
|
static pesapi_value toScript(pesapi_env env, T value[Size])
|
|
{
|
|
return pesapi_create_binary(env, value, sizeof(T) * Size);
|
|
}
|
|
|
|
static bool accept(pesapi_env env, pesapi_value value)
|
|
{
|
|
return pesapi_is_binary(env, value);
|
|
}
|
|
};
|
|
|
|
template <class T>
|
|
struct Converter<T, typename std::enable_if<std::is_copy_constructible<T>::value && std::is_constructible<T>::value &&
|
|
is_objecttype<T>::value && !is_uetype<T>::value>::type>
|
|
{
|
|
static pesapi_value toScript(pesapi_env env, T value)
|
|
{
|
|
return pesapi_native_object_to_value(env, DynamicTypeId<T>::get(&value), new T(value), true);
|
|
}
|
|
static T toCpp(pesapi_env env, pesapi_value value)
|
|
{
|
|
T* ptr = (static_cast<T*>(pesapi_get_native_object_ptr(env, value)));
|
|
return ptr ? *ptr : T{};
|
|
}
|
|
static bool accept(pesapi_env env, pesapi_value value)
|
|
{
|
|
return pesapi_is_instance_of(env, StaticTypeId<T>::get(), value);
|
|
}
|
|
};
|
|
|
|
} // namespace pesapi_impl
|
|
} // namespace PUERTS_NAMESPACE
|