1
0
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:
Sandu Liviu Catalin 2021-03-28 02:58:47 +02:00
parent 72b4f661e6
commit f95a4f9305
3 changed files with 95 additions and 9 deletions

View File

@ -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

View File

@ -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()) {

View File

@ -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;
} }