Add API_INTERFACE to scripting API bindings for implementing interfaces

This commit is contained in:
Wojtek Figat
2021-01-04 14:18:59 +01:00
parent e242dbf89f
commit 8dc5b11f51
14 changed files with 421 additions and 151 deletions

View File

@@ -44,6 +44,7 @@
// Scripting API defines (see C++ scripting documentation for more info) // Scripting API defines (see C++ scripting documentation for more info)
#define API_ENUM(...) #define API_ENUM(...)
#define API_CLASS(...) #define API_CLASS(...)
#define API_INTERFACE(...)
#define API_STRUCT(...) #define API_STRUCT(...)
#define API_FUNCTION(...) #define API_FUNCTION(...)
#define API_PROPERTY(...) #define API_PROPERTY(...)
@@ -52,3 +53,4 @@
#define API_PARAM(...) #define API_PARAM(...)
#define API_INJECT_CPP_CODE(...) #define API_INJECT_CPP_CODE(...)
#define API_AUTO_SERIALIZATION(...) public: void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; #define API_AUTO_SERIALIZATION(...) public: void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
#define DECLARE_SCRIPTING_TYPE_MINIMAL(type) public: friend class type##Internal; static struct ScriptingTypeInitializer TypeInitializer;

View File

@@ -108,7 +108,5 @@ class Dictionary;
inline T& operator&= (T& a, T b) { return (T&)((int&)a &= (int)b); } \ inline T& operator&= (T& a, T b) { return (T&)((int&)a &= (int)b); } \
inline T& operator^= (T& a, T b) { return (T&)((int&)a ^= (int)b); } inline T& operator^= (T& a, T b) { return (T&)((int&)a ^= (int)b); }
#define DECLARE_SCRIPTING_TYPE_MINIMAL(type) \ // Returns byte offset from the object pointer in vtable to the begin of the given inherited type implementation
public: \ #define VTABLE_OFFSET(type, baseType) (((intptr)static_cast<baseType*>((type*)1))-1)
friend class type##Internal; \
static struct ScriptingTypeInitializer TypeInitializer;

View File

@@ -62,6 +62,7 @@ ScriptingType::ScriptingType()
, Fullname(nullptr, 0) , Fullname(nullptr, 0)
, Type(ScriptingTypes::Script) , Type(ScriptingTypes::Script)
, BaseTypePtr(nullptr) , BaseTypePtr(nullptr)
, Interfaces(nullptr)
{ {
Script.Spawn = nullptr; Script.Spawn = nullptr;
Script.VTable = nullptr; Script.VTable = nullptr;
@@ -72,7 +73,7 @@ ScriptingType::ScriptingType()
Script.DefaultInstance = nullptr; Script.DefaultInstance = nullptr;
} }
ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, SpawnHandler spawn, const ScriptingTypeHandle& baseType, SetupScriptVTableHandler setupScriptVTable, SetupScriptObjectVTableHandler setupScriptObjectVTable) ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, SpawnHandler spawn, const ScriptingTypeHandle& baseType, SetupScriptVTableHandler setupScriptVTable, SetupScriptObjectVTableHandler setupScriptObjectVTable, const InterfaceImplementation* interfaces)
: ManagedClass(nullptr) : ManagedClass(nullptr)
, Module(module) , Module(module)
, InitRuntime(initRuntime) , InitRuntime(initRuntime)
@@ -80,6 +81,7 @@ ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* modul
, Type(ScriptingTypes::Script) , Type(ScriptingTypes::Script)
, BaseTypeHandle(baseType) , BaseTypeHandle(baseType)
, BaseTypePtr(nullptr) , BaseTypePtr(nullptr)
, Interfaces(interfaces)
, Size(size) , Size(size)
{ {
Script.Spawn = spawn; Script.Spawn = spawn;
@@ -91,13 +93,14 @@ ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* modul
Script.DefaultInstance = nullptr; Script.DefaultInstance = nullptr;
} }
ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, SpawnHandler spawn, ScriptingTypeInitializer* baseType, SetupScriptVTableHandler setupScriptVTable, SetupScriptObjectVTableHandler setupScriptObjectVTable) ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, SpawnHandler spawn, ScriptingTypeInitializer* baseType, SetupScriptVTableHandler setupScriptVTable, SetupScriptObjectVTableHandler setupScriptObjectVTable, const InterfaceImplementation* interfaces)
: ManagedClass(nullptr) : ManagedClass(nullptr)
, Module(module) , Module(module)
, InitRuntime(initRuntime) , InitRuntime(initRuntime)
, Fullname(fullname) , Fullname(fullname)
, Type(ScriptingTypes::Script) , Type(ScriptingTypes::Script)
, BaseTypePtr(baseType) , BaseTypePtr(baseType)
, Interfaces(interfaces)
, Size(size) , Size(size)
{ {
Script.Spawn = spawn; Script.Spawn = spawn;
@@ -109,26 +112,28 @@ ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* modul
Script.DefaultInstance = nullptr; Script.DefaultInstance = nullptr;
} }
ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, Ctor ctor, Dtor dtor, ScriptingTypeInitializer* baseType) ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, Ctor ctor, Dtor dtor, ScriptingTypeInitializer* baseType, const InterfaceImplementation* interfaces)
: ManagedClass(nullptr) : ManagedClass(nullptr)
, Module(module) , Module(module)
, InitRuntime(initRuntime) , InitRuntime(initRuntime)
, Fullname(fullname) , Fullname(fullname)
, Type(ScriptingTypes::Class) , Type(ScriptingTypes::Class)
, BaseTypePtr(baseType) , BaseTypePtr(baseType)
, Interfaces(interfaces)
, Size(size) , Size(size)
{ {
Class.Ctor = ctor; Class.Ctor = ctor;
Class.Dtor = dtor; Class.Dtor = dtor;
} }
ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, Ctor ctor, Dtor dtor, Copy copy, Box box, Unbox unbox, GetField getField, SetField setField, ScriptingTypeInitializer* baseType) ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, Ctor ctor, Dtor dtor, Copy copy, Box box, Unbox unbox, GetField getField, SetField setField, ScriptingTypeInitializer* baseType, const InterfaceImplementation* interfaces)
: ManagedClass(nullptr) : ManagedClass(nullptr)
, Module(module) , Module(module)
, InitRuntime(initRuntime) , InitRuntime(initRuntime)
, Fullname(fullname) , Fullname(fullname)
, Type(ScriptingTypes::Structure) , Type(ScriptingTypes::Structure)
, BaseTypePtr(baseType) , BaseTypePtr(baseType)
, Interfaces(interfaces)
, Size(size) , Size(size)
{ {
Struct.Ctor = ctor; Struct.Ctor = ctor;
@@ -140,6 +145,18 @@ ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* modul
Struct.SetField = setField; Struct.SetField = setField;
} }
ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, InitRuntimeHandler initRuntime, ScriptingTypeInitializer* baseType, const InterfaceImplementation* interfaces)
: ManagedClass(nullptr)
, Module(module)
, InitRuntime(initRuntime)
, Fullname(fullname)
, Type(ScriptingTypes::Interface)
, BaseTypePtr(baseType)
, Interfaces(interfaces)
, Size(0)
{
}
ScriptingType::ScriptingType(const ScriptingType& other) ScriptingType::ScriptingType(const ScriptingType& other)
: ManagedClass(other.ManagedClass) : ManagedClass(other.ManagedClass)
, Module(other.Module) , Module(other.Module)
@@ -148,6 +165,7 @@ ScriptingType::ScriptingType(const ScriptingType& other)
, Type(other.Type) , Type(other.Type)
, BaseTypeHandle(other.BaseTypeHandle) , BaseTypeHandle(other.BaseTypeHandle)
, BaseTypePtr(other.BaseTypePtr) , BaseTypePtr(other.BaseTypePtr)
, Interfaces(other.Interfaces)
, Size(other.Size) , Size(other.Size)
{ {
switch (other.Type) switch (other.Type)
@@ -176,6 +194,8 @@ ScriptingType::ScriptingType(const ScriptingType& other)
break; break;
case ScriptingTypes::Enum: case ScriptingTypes::Enum:
break; break;
case ScriptingTypes::Interface:
break;
default: ; default: ;
} }
} }
@@ -188,6 +208,7 @@ ScriptingType::ScriptingType(ScriptingType&& other)
, Type(other.Type) , Type(other.Type)
, BaseTypeHandle(other.BaseTypeHandle) , BaseTypeHandle(other.BaseTypeHandle)
, BaseTypePtr(other.BaseTypePtr) , BaseTypePtr(other.BaseTypePtr)
, Interfaces(other.Interfaces)
, Size(other.Size) , Size(other.Size)
{ {
switch (other.Type) switch (other.Type)
@@ -220,6 +241,8 @@ ScriptingType::ScriptingType(ScriptingType&& other)
break; break;
case ScriptingTypes::Enum: case ScriptingTypes::Enum:
break; break;
case ScriptingTypes::Interface:
break;
default: ; default: ;
} }
} }
@@ -240,6 +263,8 @@ ScriptingType::~ScriptingType()
break; break;
case ScriptingTypes::Enum: case ScriptingTypes::Enum:
break; break;
case ScriptingTypes::Interface:
break;
default: ; default: ;
} }
} }
@@ -269,16 +294,40 @@ ScriptingObject* ScriptingType::GetDefaultInstance() const
return Script.DefaultInstance; return Script.DefaultInstance;
} }
const ScriptingType::InterfaceImplementation* ScriptingType::GetInterface(const ScriptingTypeInitializer* interfaceType) const
{
const InterfaceImplementation* interfaces = Interfaces;
if (interfaces)
{
while (interfaces->InterfaceType)
{
if (interfaces->InterfaceType == interfaceType)
return interfaces;
interfaces++;
}
}
if (BaseTypeHandle)
{
return BaseTypeHandle.GetType().GetInterface(interfaceType);
}
if (BaseTypePtr)
{
return BaseTypePtr->GetType().GetInterface(interfaceType);
}
return nullptr;
}
String ScriptingType::ToString() const String ScriptingType::ToString() const
{ {
return String(Fullname.Get(), Fullname.Length()); return String(Fullname.Get(), Fullname.Length());
} }
ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::SpawnHandler spawn, ScriptingTypeInitializer* baseType, ScriptingType::SetupScriptVTableHandler setupScriptVTable, ScriptingType::SetupScriptObjectVTableHandler setupScriptObjectVTable) ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::SpawnHandler spawn, ScriptingTypeInitializer* baseType, ScriptingType::SetupScriptVTableHandler setupScriptVTable, ScriptingType::SetupScriptObjectVTableHandler setupScriptObjectVTable, const ScriptingType::InterfaceImplementation* interfaces)
: ScriptingTypeHandle(module, module->Types.Count()) : ScriptingTypeHandle(module, module->Types.Count())
{ {
// Script
module->Types.AddUninitialized(); module->Types.AddUninitialized();
new(module->Types.Get() + TypeIndex)ScriptingType(fullname, module, size, initRuntime, spawn, baseType, setupScriptVTable, setupScriptObjectVTable); new(module->Types.Get() + TypeIndex)ScriptingType(fullname, module, size, initRuntime, spawn, baseType, setupScriptVTable, setupScriptObjectVTable, interfaces);
const MString typeName(fullname.Get(), fullname.Length()); const MString typeName(fullname.Get(), fullname.Length());
#if BUILD_DEBUG #if BUILD_DEBUG
if (module->TypeNameToTypeIndex.ContainsKey(typeName)) if (module->TypeNameToTypeIndex.ContainsKey(typeName))
@@ -289,11 +338,12 @@ ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const S
module->TypeNameToTypeIndex[typeName] = TypeIndex; module->TypeNameToTypeIndex[typeName] = TypeIndex;
} }
ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::Ctor ctor, ScriptingType::Dtor dtor, ScriptingTypeInitializer* baseType) ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::Ctor ctor, ScriptingType::Dtor dtor, ScriptingTypeInitializer* baseType, const ScriptingType::InterfaceImplementation* interfaces)
: ScriptingTypeHandle(module, module->Types.Count()) : ScriptingTypeHandle(module, module->Types.Count())
{ {
// Class
module->Types.AddUninitialized(); module->Types.AddUninitialized();
new(module->Types.Get() + TypeIndex)ScriptingType(fullname, module, size, initRuntime, ctor, dtor, baseType); new(module->Types.Get() + TypeIndex)ScriptingType(fullname, module, size, initRuntime, ctor, dtor, baseType, interfaces);
const MString typeName(fullname.Get(), fullname.Length()); const MString typeName(fullname.Get(), fullname.Length());
#if BUILD_DEBUG #if BUILD_DEBUG
if (module->TypeNameToTypeIndex.ContainsKey(typeName)) if (module->TypeNameToTypeIndex.ContainsKey(typeName))
@@ -304,11 +354,28 @@ ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const S
module->TypeNameToTypeIndex[typeName] = TypeIndex; module->TypeNameToTypeIndex[typeName] = TypeIndex;
} }
ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::Ctor ctor, ScriptingType::Dtor dtor, ScriptingType::Copy copy, ScriptingType::Box box, ScriptingType::Unbox unbox, ScriptingType::GetField getField, ScriptingType::SetField setField, ScriptingTypeInitializer* baseType) ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::Ctor ctor, ScriptingType::Dtor dtor, ScriptingType::Copy copy, ScriptingType::Box box, ScriptingType::Unbox unbox, ScriptingType::GetField getField, ScriptingType::SetField setField, ScriptingTypeInitializer* baseType, const ScriptingType::InterfaceImplementation* interfaces)
: ScriptingTypeHandle(module, module->Types.Count()) : ScriptingTypeHandle(module, module->Types.Count())
{ {
// Structure
module->Types.AddUninitialized(); module->Types.AddUninitialized();
new(module->Types.Get() + TypeIndex)ScriptingType(fullname, module, size, initRuntime, ctor, dtor, copy, box, unbox, getField, setField, baseType); new(module->Types.Get() + TypeIndex)ScriptingType(fullname, module, size, initRuntime, ctor, dtor, copy, box, unbox, getField, setField, baseType, interfaces);
const MString typeName(fullname.Get(), fullname.Length());
#if BUILD_DEBUG
if (module->TypeNameToTypeIndex.ContainsKey(typeName))
{
LOG(Error, "Duplicated native typename {0} from module {1}.", String(fullname), String(module->GetName()));
}
#endif
module->TypeNameToTypeIndex[typeName] = TypeIndex;
}
ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, ScriptingType::InitRuntimeHandler initRuntime, ScriptingTypeInitializer* baseType, const ScriptingType::InterfaceImplementation* interfaces)
: ScriptingTypeHandle(module, module->Types.Count())
{
// Interface
module->Types.AddUninitialized();
new(module->Types.Get() + TypeIndex)ScriptingType(fullname, module, initRuntime, baseType, interfaces);
const MString typeName(fullname.Get(), fullname.Length()); const MString typeName(fullname.Get(), fullname.Length());
#if BUILD_DEBUG #if BUILD_DEBUG
if (module->TypeNameToTypeIndex.ContainsKey(typeName)) if (module->TypeNameToTypeIndex.ContainsKey(typeName))

View File

@@ -97,6 +97,7 @@ enum class ScriptingTypes
Structure = 1, Structure = 1,
Enum = 2, Enum = 2,
Class = 3, Class = 3,
Interface = 4,
}; };
/// <summary> /// <summary>
@@ -116,6 +117,15 @@ struct FLAXENGINE_API ScriptingType
typedef void (*GetField)(void* ptr, const String& name, Variant& value); typedef void (*GetField)(void* ptr, const String& name, Variant& value);
typedef void (*SetField)(void* ptr, const String& name, const Variant& value); typedef void (*SetField)(void* ptr, const String& name, const Variant& value);
struct InterfaceImplementation
{
// Pointer to the type of the implemented interface.
const ScriptingTypeInitializer* InterfaceType;
// The offset (in bytes) from the object pointer to the interface implementation. Used for casting object to the interface.
int16 VTableOffset;
};
/// <summary> /// <summary>
/// The managed class (cached, can be null if missing). /// The managed class (cached, can be null if missing).
/// </summary> /// </summary>
@@ -151,6 +161,11 @@ struct FLAXENGINE_API ScriptingType
/// </summary> /// </summary>
const ScriptingTypeInitializer* BaseTypePtr; const ScriptingTypeInitializer* BaseTypePtr;
/// <summary>
/// The list of interfaces implemented by this type (null if unused, list ends with null entry).
/// </summary>
const InterfaceImplementation* Interfaces;
/// <summary> /// <summary>
/// The native size of the type value (in bytes). /// The native size of the type value (in bytes).
/// </summary> /// </summary>
@@ -196,15 +211,6 @@ struct FLAXENGINE_API ScriptingType
mutable ScriptingObject* DefaultInstance; mutable ScriptingObject* DefaultInstance;
} Script; } Script;
struct
{
// Class constructor method pointer
Ctor Ctor;
// Class destructor method pointer
Dtor Dtor;
} Class;
struct struct
{ {
// Structure constructor method pointer // Structure constructor method pointer
@@ -228,13 +234,23 @@ struct FLAXENGINE_API ScriptingType
// Structure field value setter // Structure field value setter
SetField SetField; SetField SetField;
} Struct; } Struct;
struct
{
// Class constructor method pointer
Ctor Ctor;
// Class destructor method pointer
Dtor Dtor;
} Class;
}; };
ScriptingType(); ScriptingType();
ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, SpawnHandler spawn, const ScriptingTypeHandle& baseType, SetupScriptVTableHandler setupScriptVTable = nullptr, SetupScriptObjectVTableHandler setupScriptObjectVTable = nullptr); ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, SpawnHandler spawn, const ScriptingTypeHandle& baseType, SetupScriptVTableHandler setupScriptVTable = nullptr, SetupScriptObjectVTableHandler setupScriptObjectVTable = nullptr, const InterfaceImplementation* interfaces = nullptr);
ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime = DefaultInitRuntime, SpawnHandler spawn = DefaultSpawn, ScriptingTypeInitializer* baseType = nullptr, SetupScriptVTableHandler setupScriptVTable = nullptr, SetupScriptObjectVTableHandler setupScriptObjectVTable = nullptr); ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime = DefaultInitRuntime, SpawnHandler spawn = DefaultSpawn, ScriptingTypeInitializer* baseType = nullptr, SetupScriptVTableHandler setupScriptVTable = nullptr, SetupScriptObjectVTableHandler setupScriptObjectVTable = nullptr, const InterfaceImplementation* interfaces = nullptr);
ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, Ctor ctor, Dtor dtor, ScriptingTypeInitializer* baseType); ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, Ctor ctor, Dtor dtor, ScriptingTypeInitializer* baseType, const InterfaceImplementation* interfaces = nullptr);
ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, Ctor ctor, Dtor dtor, Copy copy, Box box, Unbox unbox, GetField getField, SetField setField, ScriptingTypeInitializer* baseType); ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, Ctor ctor, Dtor dtor, Copy copy, Box box, Unbox unbox, GetField getField, SetField setField, ScriptingTypeInitializer* baseType, const InterfaceImplementation* interfaces = nullptr);
ScriptingType(const StringAnsiView& fullname, BinaryModule* module, InitRuntimeHandler initRuntime, ScriptingTypeInitializer* baseType, const InterfaceImplementation* interfaces = nullptr);
ScriptingType(const ScriptingType& other); ScriptingType(const ScriptingType& other);
ScriptingType(ScriptingType&& other); ScriptingType(ScriptingType&& other);
ScriptingType& operator=(ScriptingType&& other) = delete; ScriptingType& operator=(ScriptingType&& other) = delete;
@@ -270,6 +286,11 @@ struct FLAXENGINE_API ScriptingType
/// </summary> /// </summary>
ScriptingObject* GetDefaultInstance() const; ScriptingObject* GetDefaultInstance() const;
/// <summary>
/// Gets the pointer to the implementation of the given interface type for this scripting type (including base types). Returns null if given interface is not implemented.
/// </summary>
const InterfaceImplementation* GetInterface(const ScriptingTypeInitializer* interfaceType) const;
String ToString() const; String ToString() const;
}; };
@@ -278,9 +299,10 @@ struct FLAXENGINE_API ScriptingType
/// </summary> /// </summary>
struct FLAXENGINE_API ScriptingTypeInitializer : ScriptingTypeHandle struct FLAXENGINE_API ScriptingTypeInitializer : ScriptingTypeHandle
{ {
ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime = ScriptingType::DefaultInitRuntime, ScriptingType::SpawnHandler spawn = ScriptingType::DefaultSpawn, ScriptingTypeInitializer* baseType = nullptr, ScriptingType::SetupScriptVTableHandler setupScriptVTable = nullptr, ScriptingType::SetupScriptObjectVTableHandler setupScriptObjectVTable = nullptr); ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime = ScriptingType::DefaultInitRuntime, ScriptingType::SpawnHandler spawn = ScriptingType::DefaultSpawn, ScriptingTypeInitializer* baseType = nullptr, ScriptingType::SetupScriptVTableHandler setupScriptVTable = nullptr, ScriptingType::SetupScriptObjectVTableHandler setupScriptObjectVTable = nullptr, const ScriptingType::InterfaceImplementation* interfaces = nullptr);
ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::Ctor ctor, ScriptingType::Dtor dtor, ScriptingTypeInitializer* baseType = nullptr); ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::Ctor ctor, ScriptingType::Dtor dtor, ScriptingTypeInitializer* baseType = nullptr, const ScriptingType::InterfaceImplementation* interfaces = nullptr);
ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::Ctor ctor, ScriptingType::Dtor dtor, ScriptingType::Copy copy, ScriptingType::Box box, ScriptingType::Unbox unbox, ScriptingType::GetField getField, ScriptingType::SetField setField, ScriptingTypeInitializer* baseType = nullptr); ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::Ctor ctor, ScriptingType::Dtor dtor, ScriptingType::Copy copy, ScriptingType::Box box, ScriptingType::Unbox unbox, ScriptingType::GetField getField, ScriptingType::SetField setField, ScriptingTypeInitializer* baseType = nullptr, const ScriptingType::InterfaceImplementation* interfaces = nullptr);
ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, ScriptingType::InitRuntimeHandler initRuntime, ScriptingTypeInitializer* baseType = nullptr, const ScriptingType::InterfaceImplementation* interfaces = nullptr);
}; };
/// <summary> /// <summary>

View File

@@ -22,6 +22,7 @@ namespace Flax.Build.Bindings
public virtual bool IsClass => false; public virtual bool IsClass => false;
public virtual bool IsStruct => false; public virtual bool IsStruct => false;
public virtual bool IsEnum => false; public virtual bool IsEnum => false;
public virtual bool IsInterface => false;
public virtual bool IsValueType => false; public virtual bool IsValueType => false;
public virtual bool IsScriptingObject => false; public virtual bool IsScriptingObject => false;
public virtual bool IsPod => false; public virtual bool IsPod => false;

View File

@@ -13,6 +13,7 @@ namespace Flax.Build.Bindings
{ {
public static readonly string Enum = "API_ENUM"; public static readonly string Enum = "API_ENUM";
public static readonly string Class = "API_CLASS"; public static readonly string Class = "API_CLASS";
public static readonly string Interface = "API_INTERFACE";
public static readonly string Struct = "API_STRUCT"; public static readonly string Struct = "API_STRUCT";
public static readonly string Function = "API_FUNCTION"; public static readonly string Function = "API_FUNCTION";
public static readonly string Property = "API_PROPERTY"; public static readonly string Property = "API_PROPERTY";
@@ -27,6 +28,7 @@ namespace Flax.Build.Bindings
Enum, Enum,
Class, Class,
Struct, Struct,
Interface,
}; };
} }

View File

@@ -947,9 +947,7 @@ namespace Flax.Build.Bindings
var classInfo = typeInfo as ClassInfo; var classInfo = typeInfo as ClassInfo;
var structureInfo = typeInfo as StructureInfo; var structureInfo = typeInfo as StructureInfo;
var baseType = classInfo?.BaseType ?? structureInfo?.BaseType; var baseType = classInfo?.BaseType ?? structureInfo?.BaseType;
if (baseType != null && baseType.Type == "ISerializable") if (classInfo != null && classInfo.IsBaseTypeHidden)
baseType = null;
else if (classInfo != null && classInfo.IsBaseTypeHidden)
baseType = null; baseType = null;
CppAutoSerializeFields.Clear(); CppAutoSerializeFields.Clear();
CppAutoSerializeProperties.Clear(); CppAutoSerializeProperties.Clear();
@@ -1038,6 +1036,25 @@ namespace Flax.Build.Bindings
contents.Append('}').AppendLine(); contents.Append('}').AppendLine();
} }
private static string GenerateCppInterfaceInheritanceTable(BuildData buildData, StringBuilder contents, ModuleInfo moduleInfo, ClassStructInfo typeInfo, string typeNameNative)
{
var interfacesPtr = "nullptr";
var interfaces = typeInfo.Interfaces;
if (interfaces != null)
{
interfacesPtr = typeNameNative + "_Interfaces";
contents.Append("static const ScriptingType::InterfaceImplementation ").Append(interfacesPtr).AppendLine("[] = {");
for (int i = 0; i < interfaces.Count; i++)
{
var interfaceInfo = interfaces[i];
contents.Append(" { &").Append(interfaceInfo.NativeName).Append("::TypeInitializer, (int16)VTABLE_OFFSET(").Append(typeInfo.NativeName).Append(", ").Append(interfaceInfo.NativeName).AppendLine(") },");
}
contents.AppendLine(" { nullptr, 0 },");
contents.AppendLine("};");
}
return interfacesPtr;
}
private static void GenerateCppClass(BuildData buildData, StringBuilder contents, ModuleInfo moduleInfo, ClassInfo classInfo) private static void GenerateCppClass(BuildData buildData, StringBuilder contents, ModuleInfo moduleInfo, ClassInfo classInfo)
{ {
var classTypeNameNative = classInfo.FullNameNative; var classTypeNameNative = classInfo.FullNameNative;
@@ -1311,6 +1328,9 @@ namespace Flax.Build.Bindings
contents.Append('}').Append(';').AppendLine(); contents.Append('}').Append(';').AppendLine();
contents.AppendLine(); contents.AppendLine();
// Interfaces
var interfacesTable = GenerateCppInterfaceInheritanceTable(buildData, contents, moduleInfo, classInfo, classTypeNameNative);
// Type initializer // Type initializer
contents.Append($"ScriptingTypeInitializer {classTypeNameNative}::TypeInitializer((BinaryModule*)GetBinaryModule{moduleInfo.Name}(), "); contents.Append($"ScriptingTypeInitializer {classTypeNameNative}::TypeInitializer((BinaryModule*)GetBinaryModule{moduleInfo.Name}(), ");
contents.Append($"StringAnsiView(\"{classTypeNameManaged}\", {classTypeNameManaged.Length}), "); contents.Append($"StringAnsiView(\"{classTypeNameManaged}\", {classTypeNameManaged.Length}), ");
@@ -1330,8 +1350,9 @@ namespace Flax.Build.Bindings
} }
else else
{ {
contents.Append($"&{classTypeNameInternal}Internal::Ctor, &{classTypeNameInternal}Internal::Dtor"); contents.Append($"&{classTypeNameInternal}Internal::Ctor, &{classTypeNameInternal}Internal::Dtor, nullptr");
} }
contents.Append(", ").Append(interfacesTable);
contents.Append(");"); contents.Append(");");
contents.AppendLine(); contents.AppendLine();
@@ -1526,6 +1547,42 @@ namespace Flax.Build.Bindings
} }
} }
private static void GenerateCppInterface(BuildData buildData, StringBuilder contents, ModuleInfo moduleInfo, InterfaceInfo interfaceInfo)
{
var interfaceTypeNameNative = interfaceInfo.FullNameNative;
var interfaceTypeNameManaged = interfaceInfo.FullNameManaged;
var interfaceTypeNameManagedInternalCall = interfaceTypeNameManaged.Replace('+', '/');
var interfaceTypeNameInternal = interfaceInfo.NativeName;
if (interfaceInfo.Parent != null && !(interfaceInfo.Parent is FileInfo))
interfaceTypeNameInternal = interfaceInfo.Parent.FullNameNative + '_' + interfaceTypeNameInternal;
contents.AppendLine();
contents.AppendFormat("class {0}Internal", interfaceTypeNameInternal).AppendLine();
contents.Append('{').AppendLine();
contents.AppendLine("public:");
// Runtime initialization (internal methods binding)
contents.AppendLine(" static void InitRuntime()");
contents.AppendLine(" {");
contents.AppendLine(" }").AppendLine();
contents.Append('}').Append(';').AppendLine();
contents.AppendLine();
// Type initializer
contents.Append($"ScriptingTypeInitializer {interfaceTypeNameNative}::TypeInitializer((BinaryModule*)GetBinaryModule{moduleInfo.Name}(), ");
contents.Append($"StringAnsiView(\"{interfaceTypeNameManaged}\", {interfaceTypeNameManaged.Length}), ");
contents.Append($"&{interfaceTypeNameInternal}Internal::InitRuntime");
contents.Append(");");
contents.AppendLine();
// Nested types
foreach (var apiTypeInfo in interfaceInfo.Children)
{
GenerateCppType(buildData, contents, moduleInfo, apiTypeInfo);
}
}
private static bool GenerateCppType(BuildData buildData, StringBuilder contents, ModuleInfo moduleInfo, object type) private static bool GenerateCppType(BuildData buildData, StringBuilder contents, ModuleInfo moduleInfo, object type)
{ {
if (type is ApiTypeInfo apiTypeInfo && apiTypeInfo.IsInBuild) if (type is ApiTypeInfo apiTypeInfo && apiTypeInfo.IsInBuild)
@@ -1537,6 +1594,8 @@ namespace Flax.Build.Bindings
GenerateCppClass(buildData, contents, moduleInfo, classInfo); GenerateCppClass(buildData, contents, moduleInfo, classInfo);
else if (type is StructureInfo structureInfo) else if (type is StructureInfo structureInfo)
GenerateCppStruct(buildData, contents, moduleInfo, structureInfo); GenerateCppStruct(buildData, contents, moduleInfo, structureInfo);
else if (type is InterfaceInfo interfaceInfo)
GenerateCppInterface(buildData, contents, moduleInfo, interfaceInfo);
else if (type is InjectCppCodeInfo injectCppCodeInfo) else if (type is InjectCppCodeInfo injectCppCodeInfo)
contents.AppendLine(injectCppCodeInfo.Code); contents.AppendLine(injectCppCodeInfo.Code);
else else

View File

@@ -383,6 +383,95 @@ namespace Flax.Build.Bindings
return name; return name;
} }
private static void ParseInheritance(ref ParsingContext context, ClassStructInfo desc, out bool isFinal)
{
desc.BaseType = null;
desc.BaseTypeInheritance = AccessLevel.Private;
var token = context.Tokenizer.NextToken();
isFinal = token.Value == "final";
if (isFinal)
token = context.Tokenizer.NextToken();
if (token.Type == TokenType.Colon)
{
while (token.Type != TokenType.LeftCurlyBrace)
{
var accessToken = context.Tokenizer.ExpectToken(TokenType.Identifier);
switch (accessToken.Value)
{
case "public":
desc.BaseTypeInheritance = AccessLevel.Public;
token = context.Tokenizer.ExpectToken(TokenType.Identifier);
break;
case "protected":
desc.BaseTypeInheritance = AccessLevel.Protected;
token = context.Tokenizer.ExpectToken(TokenType.Identifier);
break;
case "private":
token = context.Tokenizer.ExpectToken(TokenType.Identifier);
break;
default:
token = accessToken;
break;
}
var baseTypeInfo = new TypeInfo
{
Type = token.Value,
};
if (token.Value.Length > 2 && token.Value[0] == 'I' && char.IsUpper(token.Value[1]))
{
// Interface
if (desc.InterfaceNames == null)
desc.InterfaceNames = new List<TypeInfo>();
desc.InterfaceNames.Add(baseTypeInfo);
token = context.Tokenizer.NextToken();
continue;
}
if (desc.BaseType != null)
{
// Allow for multiple base classes, just the first one needs to be a valid base type
break;
throw new Exception($"Invalid '{desc.Name}' inheritance (only single base class is allowed for scripting types, excluding interfaces).");
}
desc.BaseType = baseTypeInfo;
token = context.Tokenizer.NextToken();
if (token.Type == TokenType.LeftCurlyBrace)
{
break;
}
if (token.Type == TokenType.LeftAngleBracket)
{
var genericType = context.Tokenizer.ExpectToken(TokenType.Identifier);
token = context.Tokenizer.ExpectToken(TokenType.RightAngleBracket);
desc.BaseType.GenericArgs = new List<TypeInfo>
{
new TypeInfo
{
Type = genericType.Value,
}
};
// TODO: find better way to resolve this (custom base type attribute?)
if (desc.BaseType.Type == "ShaderAssetTypeBase")
{
desc.BaseType = desc.BaseType.GenericArgs[0];
}
token = context.Tokenizer.NextToken();
}
}
token = context.Tokenizer.PreviousToken();
}
else
{
// No base type
token = context.Tokenizer.PreviousToken();
}
}
private static ClassInfo ParseClass(ref ParsingContext context) private static ClassInfo ParseClass(ref ParsingContext context)
{ {
var desc = new ClassInfo var desc = new ClassInfo
@@ -410,64 +499,8 @@ namespace Flax.Build.Bindings
// Read name // Read name
desc.Name = desc.NativeName = ParseName(ref context); desc.Name = desc.NativeName = ParseName(ref context);
// Read class inheritance // Read inheritance
token = context.Tokenizer.NextToken(); ParseInheritance(ref context, desc, out var isFinal);
var isFinal = token.Value == "final";
if (isFinal)
token = context.Tokenizer.NextToken();
if (token.Type == TokenType.Colon)
{
// Current class does have inheritance defined
var accessToken = context.Tokenizer.ExpectToken(TokenType.Identifier);
switch (accessToken.Value)
{
case "public":
desc.BaseTypeInheritance = AccessLevel.Public;
token = context.Tokenizer.ExpectToken(TokenType.Identifier);
break;
case "protected":
desc.BaseTypeInheritance = AccessLevel.Protected;
token = context.Tokenizer.ExpectToken(TokenType.Identifier);
break;
case "private":
token = context.Tokenizer.ExpectToken(TokenType.Identifier);
break;
}
desc.BaseType = new TypeInfo
{
Type = token.Value,
};
token = context.Tokenizer.NextToken();
if (token.Type == TokenType.LeftAngleBracket)
{
var genericType = context.Tokenizer.ExpectToken(TokenType.Identifier);
context.Tokenizer.ExpectToken(TokenType.RightAngleBracket);
desc.BaseType.GenericArgs = new List<TypeInfo>
{
new TypeInfo
{
Type = genericType.Value,
}
};
// TODO: find better way to resolve this (custom base type attribute?)
if (desc.BaseType.Type == "ShaderAssetTypeBase")
{
desc.BaseType = desc.BaseType.GenericArgs[0];
}
}
else
{
token = context.Tokenizer.PreviousToken();
}
}
else
{
// No base type
token = context.Tokenizer.PreviousToken();
desc.BaseType = null;
}
// Process tag parameters // Process tag parameters
foreach (var tag in tagParams) foreach (var tag in tagParams)
@@ -523,6 +556,68 @@ namespace Flax.Build.Bindings
return desc; return desc;
} }
private static InterfaceInfo ParseInterface(ref ParsingContext context)
{
var desc = new InterfaceInfo
{
Children = new List<ApiTypeInfo>(),
Access = context.CurrentAccessLevel,
};
// Read the documentation comment
desc.Comment = ParseComment(ref context);
// Read parameters from the tag
var tagParams = ParseTagParameters(ref context);
// Read 'class' keyword
var token = context.Tokenizer.NextToken();
if (token.Value != "class")
throw new Exception($"Invalid API_INTERFACE usage (expected 'class' keyword but got '{token.Value} {context.Tokenizer.NextToken().Value}').");
// Read name
desc.Name = desc.NativeName = ParseName(ref context);
if (desc.Name.Length < 2 || desc.Name[0] != 'I' || !char.IsUpper(desc.Name[1]))
throw new Exception($"Invalid API_INTERFACE name '{desc.Name}' (it must start with 'I' character followed by the uppercase character).");
// Read inheritance
ParseInheritance(ref context, desc, out _);
// Process tag parameters
foreach (var tag in tagParams)
{
switch (tag.Tag.ToLower())
{
case "public":
desc.Access = AccessLevel.Public;
break;
case "protected":
desc.Access = AccessLevel.Protected;
break;
case "private":
desc.Access = AccessLevel.Private;
break;
case "inbuild":
desc.IsInBuild = true;
break;
case "attributes":
desc.Attributes = tag.Value;
break;
case "name":
desc.Name = tag.Value;
break;
case "namespace":
desc.Namespace = tag.Value;
break;
default:
Log.Warning($"Unknown or not supported tag parameter {tag} used on interface {desc.Name} at line {context.Tokenizer.CurrentLine}");
break;
}
}
return desc;
}
private static FunctionInfo ParseFunction(ref ParsingContext context) private static FunctionInfo ParseFunction(ref ParsingContext context)
{ {
var desc = new FunctionInfo var desc = new FunctionInfo
@@ -875,55 +970,8 @@ namespace Flax.Build.Bindings
// Read name // Read name
desc.Name = desc.NativeName = ParseName(ref context); desc.Name = desc.NativeName = ParseName(ref context);
// Read structure inheritance // Read inheritance
token = context.Tokenizer.NextToken(); ParseInheritance(ref context, desc, out _);
if (token.Type == TokenType.Colon)
{
// Current class does have inheritance defined
var accessToken = context.Tokenizer.ExpectToken(TokenType.Identifier);
switch (accessToken.Value)
{
case "public":
token = context.Tokenizer.ExpectToken(TokenType.Identifier);
break;
case "protected":
token = context.Tokenizer.ExpectToken(TokenType.Identifier);
break;
case "private":
token = context.Tokenizer.ExpectToken(TokenType.Identifier);
break;
default:
token = accessToken;
break;
}
desc.BaseType = new TypeInfo
{
Type = token.Value,
};
token = context.Tokenizer.NextToken();
if (token.Type == TokenType.LeftAngleBracket)
{
var genericType = context.Tokenizer.ExpectToken(TokenType.Identifier);
context.Tokenizer.ExpectToken(TokenType.RightAngleBracket);
desc.BaseType.GenericArgs = new List<TypeInfo>
{
new TypeInfo
{
Type = genericType.Value,
}
};
}
else
{
token = context.Tokenizer.PreviousToken();
}
}
else
{
// No base type
token = context.Tokenizer.PreviousToken();
}
// Process tag parameters // Process tag parameters
foreach (var tag in tagParams) foreach (var tag in tagParams)

View File

@@ -254,6 +254,16 @@ namespace Flax.Build.Bindings
var injectCppCodeInfo = ParseInjectCppCode(ref context); var injectCppCodeInfo = ParseInjectCppCode(ref context);
fileInfo.AddChild(injectCppCodeInfo); fileInfo.AddChild(injectCppCodeInfo);
} }
else if (string.Equals(token.Value, ApiTokens.Interface, StringComparison.Ordinal))
{
if (!(context.ScopeInfo is FileInfo))
throw new NotImplementedException("TODO: add support for nested interfaces in scripting API");
var interfaceInfo = ParseInterface(ref context);
scopeType = interfaceInfo;
context.ScopeInfo.AddChild(scopeType);
context.CurrentAccessLevel = AccessLevel.Public;
}
else if (string.Equals(token.Value, ApiTokens.AutoSerialization, StringComparison.Ordinal)) else if (string.Equals(token.Value, ApiTokens.AutoSerialization, StringComparison.Ordinal))
{ {
if (context.ScopeInfo is ClassInfo classInfo) if (context.ScopeInfo is ClassInfo classInfo)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2012-2019 Wojciech Figat. All rights reserved. // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -8,7 +8,7 @@ namespace Flax.Build.Bindings
/// <summary> /// <summary>
/// The native class information for bindings generator. /// The native class information for bindings generator.
/// </summary> /// </summary>
public class ClassInfo : ApiTypeInfo public class ClassInfo : ClassStructInfo
{ {
private static readonly HashSet<string> InBuildScriptingObjectTypes = new HashSet<string> private static readonly HashSet<string> InBuildScriptingObjectTypes = new HashSet<string>
{ {
@@ -22,9 +22,6 @@ namespace Flax.Build.Bindings
"Actor", "Actor",
}; };
public AccessLevel Access;
public TypeInfo BaseType;
public AccessLevel BaseTypeInheritance;
public bool IsBaseTypeHidden; public bool IsBaseTypeHidden;
public bool IsStatic; public bool IsStatic;
public bool IsSealed; public bool IsSealed;
@@ -52,7 +49,7 @@ namespace Flax.Build.Bindings
base.Init(buildData); base.Init(buildData);
// Internal base types are usually hidden from bindings (used in core-only internally) // Internal base types are usually hidden from bindings (used in core-only internally)
IsBaseTypeHidden = BaseTypeInheritance == AccessLevel.Private || BaseType.Type == "ISerializable"; IsBaseTypeHidden = BaseTypeInheritance == AccessLevel.Private || BaseType == null;
// Cache if it it Scripting Object type // Cache if it it Scripting Object type
if (InBuildScriptingObjectTypes.Contains(Name)) if (InBuildScriptingObjectTypes.Contains(Name))

View File

@@ -0,0 +1,40 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
namespace Flax.Build.Bindings
{
/// <summary>
/// The native class/structure information for bindings generator.
/// </summary>
public abstract class ClassStructInfo : ApiTypeInfo
{
public AccessLevel Access;
public AccessLevel BaseTypeInheritance;
public TypeInfo BaseType;
public List<InterfaceInfo> Interfaces; // Optional
public List<TypeInfo> InterfaceNames; // Optional
public override void Init(Builder.BuildData buildData)
{
base.Init(buildData);
if (Interfaces == null && InterfaceNames != null && InterfaceNames.Count != 0)
{
Interfaces = new List<InterfaceInfo>();
for (var i = 0; i < InterfaceNames.Count; i++)
{
var interfaceName = InterfaceNames[i];
var apiTypeInfo = BindingsGenerator.FindApiTypeInfo(buildData, interfaceName, this);
if (apiTypeInfo is InterfaceInfo interfaceInfo)
{
Interfaces.Add(interfaceInfo);
}
}
if (Interfaces.Count == 0)
Interfaces = null;
}
}
}
}

View File

@@ -0,0 +1,24 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
namespace Flax.Build.Bindings
{
/// <summary>
/// The native class/structure interface information for bindings generator.
/// </summary>
public class InterfaceInfo : ClassStructInfo
{
public override bool IsInterface => true;
public override void AddChild(ApiTypeInfo apiTypeInfo)
{
apiTypeInfo.Namespace = null;
base.AddChild(apiTypeInfo);
}
public override string ToString()
{
return "interface " + Name;
}
}
}

View File

@@ -8,10 +8,8 @@ namespace Flax.Build.Bindings
/// <summary> /// <summary>
/// The native structure information for bindings generator. /// The native structure information for bindings generator.
/// </summary> /// </summary>
public class StructureInfo : ApiTypeInfo public class StructureInfo : ClassStructInfo
{ {
public AccessLevel Access;
public TypeInfo BaseType;
public List<FieldInfo> Fields; public List<FieldInfo> Fields;
public List<FunctionInfo> Functions; public List<FunctionInfo> Functions;
public bool IsAutoSerialization; public bool IsAutoSerialization;
@@ -27,7 +25,7 @@ namespace Flax.Build.Bindings
{ {
base.Init(buildData); base.Init(buildData);
if (ForceNoPod) if (ForceNoPod || (InterfaceNames != null && InterfaceNames.Count != 0))
{ {
_isPod = false; _isPod = false;
return; return;

View File

@@ -69,12 +69,14 @@
<Compile Include="Bindings\BindingsGenerator.CSharp.cs" /> <Compile Include="Bindings\BindingsGenerator.CSharp.cs" />
<Compile Include="Bindings\BindingsGenerator.Parsing.cs" /> <Compile Include="Bindings\BindingsGenerator.Parsing.cs" />
<Compile Include="Bindings\ClassInfo.cs" /> <Compile Include="Bindings\ClassInfo.cs" />
<Compile Include="Bindings\ClassStructInfo.cs" />
<Compile Include="Bindings\EnumInfo.cs" /> <Compile Include="Bindings\EnumInfo.cs" />
<Compile Include="Bindings\EventInfo.cs" /> <Compile Include="Bindings\EventInfo.cs" />
<Compile Include="Bindings\FieldInfo.cs" /> <Compile Include="Bindings\FieldInfo.cs" />
<Compile Include="Bindings\FileInfo.cs" /> <Compile Include="Bindings\FileInfo.cs" />
<Compile Include="Bindings\InheritanceInfo.cs" /> <Compile Include="Bindings\InheritanceInfo.cs" />
<Compile Include="Bindings\InjectCppCodeInfo.cs" /> <Compile Include="Bindings\InjectCppCodeInfo.cs" />
<Compile Include="Bindings\InterfaceInfo.cs" />
<Compile Include="Bindings\LangType.cs" /> <Compile Include="Bindings\LangType.cs" />
<Compile Include="Bindings\MemberInfo.cs" /> <Compile Include="Bindings\MemberInfo.cs" />
<Compile Include="Bindings\FunctionInfo.cs" /> <Compile Include="Bindings\FunctionInfo.cs" />