mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 00:37:15 +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);
|
||||
// Configure error handling
|
||||
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
|
||||
NullArray() = Array();
|
||||
@ -575,6 +577,8 @@ void Core::Terminate(bool shutdown)
|
||||
m_PendingScripts.clear(); // Just in case
|
||||
// Specify that no scripts are left executed
|
||||
m_Executed = false;
|
||||
// Retrieve the VM context before closing
|
||||
VMContext * ctx = GetVMContext(m_VM);
|
||||
// Assertions during close may cause double delete/close!
|
||||
HSQUIRRELVM sq_vm = m_VM;
|
||||
m_VM = nullptr;
|
||||
@ -584,8 +588,33 @@ void Core::Terminate(bool shutdown)
|
||||
//_Func->SendPluginCommand(0xBAAAAAAD, "");
|
||||
// Release any callbacks from the logger
|
||||
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
|
||||
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");
|
||||
// Tell modules to do their monkey business
|
||||
|
@ -82,6 +82,7 @@ public:
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Class(HSQUIRRELVM v, const string& className, bool createClass = true) : Object(false) {
|
||||
if (createClass && !ClassType<C>::hasClassData(v)) {
|
||||
/*
|
||||
sq_pushregistrytable(v);
|
||||
sq_pushstring(v, "__classes", -1);
|
||||
if (SQ_FAILED(sq_rawget(v, -2))) {
|
||||
@ -96,8 +97,11 @@ public:
|
||||
sq_setreleasehook(v, -1, &cleanup_hook);
|
||||
sq_rawset(v, -3);
|
||||
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()) {
|
||||
@ -958,6 +962,7 @@ public:
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
DerivedClass(HSQUIRRELVM v, const string& className) : Class<C, A>(v, string(), false) {
|
||||
if (!ClassType<C>::hasClassData(v)) {
|
||||
/*
|
||||
sq_pushregistrytable(v);
|
||||
sq_pushstring(v, "__classes", -1);
|
||||
if (SQ_FAILED(sq_rawget(v, -2))) {
|
||||
@ -972,9 +977,12 @@ public:
|
||||
sq_setreleasehook(v, -1, &cleanup_hook);
|
||||
sq_rawset(v, -3);
|
||||
sq_pop(v, 2);
|
||||
|
||||
*/
|
||||
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()) {
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <typeinfo>
|
||||
|
||||
#include "sqratUtil.h"
|
||||
#include "Core/VecMap.hpp"
|
||||
|
||||
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
|
||||
template<class C>
|
||||
struct ClassData {
|
||||
// Base class for ClassData to provide a common interface
|
||||
struct AbstractClassData {
|
||||
HSQOBJECT classObj{};
|
||||
HSQOBJECT getTable{};
|
||||
HSQOBJECT setTable{};
|
||||
SharedPtr<std::unordered_map<C*, HSQOBJECT>> instances;
|
||||
SharedPtr<AbstractStaticClassData> staticData;
|
||||
AbstractClassData() = default;
|
||||
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
|
||||
/*
|
||||
class _ClassType_helper {
|
||||
@ -118,6 +159,9 @@ class ClassType {
|
||||
public:
|
||||
|
||||
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_pushstring(vm, "__classes", -1);
|
||||
#ifndef NDEBUG
|
||||
@ -137,6 +181,7 @@ public:
|
||||
sq_getuserdata(vm, -1, (SQUserPointer*)&ud, nullptr);
|
||||
sq_pop(vm, 3);
|
||||
return *ud;
|
||||
*/
|
||||
}
|
||||
|
||||
//static WeakPtr<AbstractStaticClassData>& getStaticClassData() {
|
||||
@ -149,6 +194,9 @@ public:
|
||||
static inline bool hasClassData(HSQUIRRELVM vm) {
|
||||
//if (!getStaticClassData().Expired()) {
|
||||
if (StaticClassTypeTag<C>::Get()!=nullptr) {
|
||||
VMContext* ctx = reinterpret_cast<VMContext*>(sq_getforeignptr(vm));
|
||||
return ctx->classes.exists(ClassName());
|
||||
/*
|
||||
sq_pushregistrytable(vm);
|
||||
sq_pushstring(vm, "__classes", -1);
|
||||
if (SQ_SUCCEEDED(sq_rawget(vm, -2))) {
|
||||
@ -160,6 +208,7 @@ public:
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
sq_pop(vm, 1);
|
||||
*/
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user