mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 08:47:17 +01:00
Experimental changes to binding utility.
This commit is contained in:
parent
72b4f661e6
commit
f95a4f9305
@ -307,6 +307,8 @@ bool Core::Initialize()
|
|||||||
DefaultVM::Set(m_VM);
|
DefaultVM::Set(m_VM);
|
||||||
// Configure error handling
|
// Configure error handling
|
||||||
ErrorHandling::Enable(conf.GetBoolValue("Squirrel", "ErrorHandling", true));
|
ErrorHandling::Enable(conf.GetBoolValue("Squirrel", "ErrorHandling", true));
|
||||||
|
// Create VM context instance
|
||||||
|
sq_setforeignptr(m_VM, new VMContext());
|
||||||
|
|
||||||
// Prevent common null objects from using dead virtual machines
|
// Prevent common null objects from using dead virtual machines
|
||||||
NullArray() = Array();
|
NullArray() = Array();
|
||||||
@ -575,6 +577,8 @@ void Core::Terminate(bool shutdown)
|
|||||||
m_PendingScripts.clear(); // Just in case
|
m_PendingScripts.clear(); // Just in case
|
||||||
// Specify that no scripts are left executed
|
// Specify that no scripts are left executed
|
||||||
m_Executed = false;
|
m_Executed = false;
|
||||||
|
// Retrieve the VM context before closing
|
||||||
|
VMContext * ctx = GetVMContext(m_VM);
|
||||||
// Assertions during close may cause double delete/close!
|
// Assertions during close may cause double delete/close!
|
||||||
HSQUIRRELVM sq_vm = m_VM;
|
HSQUIRRELVM sq_vm = m_VM;
|
||||||
m_VM = nullptr;
|
m_VM = nullptr;
|
||||||
@ -584,8 +588,33 @@ void Core::Terminate(bool shutdown)
|
|||||||
//_Func->SendPluginCommand(0xBAAAAAAD, "");
|
//_Func->SendPluginCommand(0xBAAAAAAD, "");
|
||||||
// Release any callbacks from the logger
|
// Release any callbacks from the logger
|
||||||
Logger::Get().Release();
|
Logger::Get().Release();
|
||||||
|
cLogDbg(m_Verbosity >= 2, "Closing Virtual Machine");
|
||||||
|
// Release class object references before closing the VM
|
||||||
|
for (auto & c : ctx->classes)
|
||||||
|
{
|
||||||
|
c.second->Release();
|
||||||
|
}
|
||||||
// Attempt to close the VM
|
// Attempt to close the VM
|
||||||
sq_close(sq_vm);
|
sq_close(sq_vm);
|
||||||
|
// Reset class objects before destructor is invoked
|
||||||
|
for (auto & c : ctx->classes)
|
||||||
|
{
|
||||||
|
c.second->Reset();
|
||||||
|
}
|
||||||
|
// Go through each class and check for leftover objects
|
||||||
|
for (auto & c : ctx->classes)
|
||||||
|
{
|
||||||
|
// Retrieve the number of elements left in the container
|
||||||
|
size_t n = c.second->InstanceCount();
|
||||||
|
// Log however many are left, if any
|
||||||
|
if (n != 0)
|
||||||
|
{
|
||||||
|
cLogDbg(m_Verbosity >= 1, "%zu leaked (%s) objects", n, c.first.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cLogDbg(m_Verbosity >= 2, "Destroying VM Context");
|
||||||
|
// Destroy the VM context, if any
|
||||||
|
delete ctx;
|
||||||
|
|
||||||
//cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins to release the virtual machine");
|
//cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins to release the virtual machine");
|
||||||
// Tell modules to do their monkey business
|
// Tell modules to do their monkey business
|
||||||
|
@ -82,6 +82,7 @@ public:
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
Class(HSQUIRRELVM v, const string& className, bool createClass = true) : Object(false) {
|
Class(HSQUIRRELVM v, const string& className, bool createClass = true) : Object(false) {
|
||||||
if (createClass && !ClassType<C>::hasClassData(v)) {
|
if (createClass && !ClassType<C>::hasClassData(v)) {
|
||||||
|
/*
|
||||||
sq_pushregistrytable(v);
|
sq_pushregistrytable(v);
|
||||||
sq_pushstring(v, "__classes", -1);
|
sq_pushstring(v, "__classes", -1);
|
||||||
if (SQ_FAILED(sq_rawget(v, -2))) {
|
if (SQ_FAILED(sq_rawget(v, -2))) {
|
||||||
@ -96,8 +97,11 @@ public:
|
|||||||
sq_setreleasehook(v, -1, &cleanup_hook);
|
sq_setreleasehook(v, -1, &cleanup_hook);
|
||||||
sq_rawset(v, -3);
|
sq_rawset(v, -3);
|
||||||
sq_pop(v, 2);
|
sq_pop(v, 2);
|
||||||
|
*/
|
||||||
ClassData<C>* cd = *ud;
|
//ClassData<C>* cd = *ud;
|
||||||
|
auto* cd = new ClassData<C>();
|
||||||
|
VMContext::ClsPtr ptr(static_cast<AbstractClassData*>(cd));
|
||||||
|
GetVMContext(v)->classes.try_emplace(className, std::move(ptr));
|
||||||
|
|
||||||
//if (ClassType<C>::getStaticClassData().Expired()) {
|
//if (ClassType<C>::getStaticClassData().Expired()) {
|
||||||
if (!ClassType<C>::getStaticClassData()) {
|
if (!ClassType<C>::getStaticClassData()) {
|
||||||
@ -958,6 +962,7 @@ public:
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
DerivedClass(HSQUIRRELVM v, const string& className) : Class<C, A>(v, string(), false) {
|
DerivedClass(HSQUIRRELVM v, const string& className) : Class<C, A>(v, string(), false) {
|
||||||
if (!ClassType<C>::hasClassData(v)) {
|
if (!ClassType<C>::hasClassData(v)) {
|
||||||
|
/*
|
||||||
sq_pushregistrytable(v);
|
sq_pushregistrytable(v);
|
||||||
sq_pushstring(v, "__classes", -1);
|
sq_pushstring(v, "__classes", -1);
|
||||||
if (SQ_FAILED(sq_rawget(v, -2))) {
|
if (SQ_FAILED(sq_rawget(v, -2))) {
|
||||||
@ -972,9 +977,12 @@ public:
|
|||||||
sq_setreleasehook(v, -1, &cleanup_hook);
|
sq_setreleasehook(v, -1, &cleanup_hook);
|
||||||
sq_rawset(v, -3);
|
sq_rawset(v, -3);
|
||||||
sq_pop(v, 2);
|
sq_pop(v, 2);
|
||||||
|
*/
|
||||||
ClassData<B>* bd = ClassType<B>::getClassData(v);
|
ClassData<B>* bd = ClassType<B>::getClassData(v);
|
||||||
ClassData<C>* cd = *ud;
|
//ClassData<C>* cd = *ud;
|
||||||
|
auto* cd = new ClassData<C>();
|
||||||
|
VMContext::ClsPtr ptr(static_cast<AbstractClassData*>(cd));
|
||||||
|
GetVMContext(v)->classes.try_emplace(className, std::move(ptr));
|
||||||
|
|
||||||
//if (ClassType<C>::getStaticClassData()->Expired()) {
|
//if (ClassType<C>::getStaticClassData()->Expired()) {
|
||||||
if (!ClassType<C>::getStaticClassData()) {
|
if (!ClassType<C>::getStaticClassData()) {
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
|
||||||
#include "sqratUtil.h"
|
#include "sqratUtil.h"
|
||||||
|
#include "Core/VecMap.hpp"
|
||||||
|
|
||||||
namespace Sqrat
|
namespace Sqrat
|
||||||
{
|
{
|
||||||
@ -82,16 +83,56 @@ struct StaticClassData : public AbstractStaticClassData, public StaticClassTypeT
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Every Squirrel class object created by Sqrat in every VM has its own unique ClassData object stored in the registry table of the VM
|
// Base class for ClassData to provide a common interface
|
||||||
template<class C>
|
struct AbstractClassData {
|
||||||
struct ClassData {
|
|
||||||
HSQOBJECT classObj{};
|
HSQOBJECT classObj{};
|
||||||
HSQOBJECT getTable{};
|
HSQOBJECT getTable{};
|
||||||
HSQOBJECT setTable{};
|
HSQOBJECT setTable{};
|
||||||
SharedPtr<std::unordered_map<C*, HSQOBJECT>> instances;
|
AbstractClassData() = default;
|
||||||
SharedPtr<AbstractStaticClassData> staticData;
|
virtual ~AbstractClassData() { Release(); }
|
||||||
|
virtual size_t InstanceCount() = 0;
|
||||||
|
// This should be called before closing the VM
|
||||||
|
void Release() {
|
||||||
|
// Should we release class object?
|
||||||
|
if (!sq_isnull(classObj)) {
|
||||||
|
sq_release(SqVM(), &classObj);
|
||||||
|
}
|
||||||
|
// Should we release get table object?
|
||||||
|
if (!sq_isnull(getTable)) {
|
||||||
|
sq_release(SqVM(), &getTable);
|
||||||
|
}
|
||||||
|
// Should we release set table object?
|
||||||
|
if (!sq_isnull(setTable)) {
|
||||||
|
sq_release(SqVM(), &setTable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Reset() {
|
||||||
|
sq_resetobject(&classObj);
|
||||||
|
sq_resetobject(&getTable);
|
||||||
|
sq_resetobject(&setTable);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Every Squirrel class object created by Sqrat in every VM has its own unique ClassData object stored in the registry table of the VM
|
||||||
|
template<class C>
|
||||||
|
struct ClassData : public AbstractClassData {
|
||||||
|
SharedPtr<std::unordered_map<C*, HSQOBJECT>> instances{};
|
||||||
|
SharedPtr<AbstractStaticClassData> staticData{};
|
||||||
|
ClassData() = default;
|
||||||
|
~ClassData() override = default;
|
||||||
|
size_t InstanceCount() override { return instances->size(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Inrternal structure used to keep track of created objects.
|
||||||
|
struct VMContext {
|
||||||
|
using ClsPtr = std::unique_ptr<AbstractClassData>;
|
||||||
|
VecMap<std::string, ClsPtr> classes{};
|
||||||
|
VMContext() = default;
|
||||||
|
~VMContext() = default;
|
||||||
|
};
|
||||||
|
// Retrieve the associated context from VM
|
||||||
|
inline VMContext* GetVMContext(HSQUIRRELVM vm) { return reinterpret_cast<VMContext*>(sq_getforeignptr(vm)); }
|
||||||
|
|
||||||
// Lookup static class data by type_info rather than a template because C++ cannot export generic templates
|
// Lookup static class data by type_info rather than a template because C++ cannot export generic templates
|
||||||
/*
|
/*
|
||||||
class _ClassType_helper {
|
class _ClassType_helper {
|
||||||
@ -118,6 +159,9 @@ class ClassType {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
static inline ClassData<C>* getClassData(HSQUIRRELVM vm) {
|
static inline ClassData<C>* getClassData(HSQUIRRELVM vm) {
|
||||||
|
auto* ctx = reinterpret_cast<VMContext*>(sq_getforeignptr(vm));
|
||||||
|
return static_cast<ClassData<C>*>(ctx->classes[ClassName()].get());
|
||||||
|
/*
|
||||||
sq_pushregistrytable(vm);
|
sq_pushregistrytable(vm);
|
||||||
sq_pushstring(vm, "__classes", -1);
|
sq_pushstring(vm, "__classes", -1);
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
@ -137,6 +181,7 @@ public:
|
|||||||
sq_getuserdata(vm, -1, (SQUserPointer*)&ud, nullptr);
|
sq_getuserdata(vm, -1, (SQUserPointer*)&ud, nullptr);
|
||||||
sq_pop(vm, 3);
|
sq_pop(vm, 3);
|
||||||
return *ud;
|
return *ud;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
//static WeakPtr<AbstractStaticClassData>& getStaticClassData() {
|
//static WeakPtr<AbstractStaticClassData>& getStaticClassData() {
|
||||||
@ -149,6 +194,9 @@ public:
|
|||||||
static inline bool hasClassData(HSQUIRRELVM vm) {
|
static inline bool hasClassData(HSQUIRRELVM vm) {
|
||||||
//if (!getStaticClassData().Expired()) {
|
//if (!getStaticClassData().Expired()) {
|
||||||
if (StaticClassTypeTag<C>::Get()!=nullptr) {
|
if (StaticClassTypeTag<C>::Get()!=nullptr) {
|
||||||
|
VMContext* ctx = reinterpret_cast<VMContext*>(sq_getforeignptr(vm));
|
||||||
|
return ctx->classes.exists(ClassName());
|
||||||
|
/*
|
||||||
sq_pushregistrytable(vm);
|
sq_pushregistrytable(vm);
|
||||||
sq_pushstring(vm, "__classes", -1);
|
sq_pushstring(vm, "__classes", -1);
|
||||||
if (SQ_SUCCEEDED(sq_rawget(vm, -2))) {
|
if (SQ_SUCCEEDED(sq_rawget(vm, -2))) {
|
||||||
@ -160,6 +208,7 @@ public:
|
|||||||
sq_pop(vm, 1);
|
sq_pop(vm, 1);
|
||||||
}
|
}
|
||||||
sq_pop(vm, 1);
|
sq_pop(vm, 1);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user