Improve Custom Wrappers
All checks were successful
CI / Build (push) Successful in 28s

This commit is contained in:
TheBrokenRail 2025-04-14 13:54:55 -04:00
parent b858a2fc1a
commit e42f46d6cc
5 changed files with 41 additions and 37 deletions

View File

@ -1,7 +1,11 @@
// Get Custom Wrapper From Object
template <typename Data>
Data **__custom_get(typename Data::__Self *self) {
return (Data **) (self + 1);
}
template <typename Data>
Data *custom_get(typename Data::__Self *self) {
return (Data *) (self + 1);
return *__custom_get<Data>(self);
}
// Duplicate VTable
@ -32,43 +36,25 @@ struct __CustomBase {
// Prevent Copying
__PREVENT_COPY(__CustomBase);
#define get_self(ptr) (((__Self *) ptr) - 1)
#ifdef {{ BUILDING_SYMBOLS_GUARD }}
// Constructor
__CustomBase():
self(get_self(this)) {}
self(__Self::allocate(sizeof(this)))
{
*__custom_get<__CustomBase>(self) = this;
}
#else
// Prevent Construction
__PREVENT_JUST_CONSTRUCTION(__CustomBase);
#endif
private:
// Destructor
virtual ~__CustomBase() = default;
// Allocation
void *operator new(const size_t count) {
const size_t size = sizeof(__Self) + count;
__Self *out = (__Self *) ::operator new(size);
return (void *) custom_get<__CustomBase>(out);
__Self *(*__VTable::*selected_destructor)(__Self *) = &__VTable::destructor_deleting;
public:
virtual ~__CustomBase() {
(__VTable::base->*selected_destructor)(self);
}
void *operator new[](size_t) = delete;
// Deallocation
void operator delete(__CustomBase *ptr, std::destroying_delete_t) {
if (ptr) {
__Self *self = ptr->self;
// This Calls The Actual Destructor
self->vtable->destructor_deleting(self);
}
}
void operator delete(void *ptr) {
if (ptr) {
// Issue During Construction, Just Free Memory
::operator delete(get_self(ptr));
}
}
#undef get_self
void operator delete[](void *) = delete;
protected:
// VTable
@ -76,8 +62,10 @@ protected:
// Patch Destructors
#define patch(type) \
vtable->type = [](__Self *self) { \
custom_get<__CustomBase>(self)->~__CustomBase(); \
return __VTable::base->type(self); \
__CustomBase *obj = custom_get<__CustomBase>(self); \
obj->selected_destructor = &__VTable::type; \
delete obj; \
return self; \
}
patch(destructor_complete);
patch(destructor_deleting);

View File

@ -1,3 +1,6 @@
#pragma once
// Type Traits
#include <type_traits>
// Internal Macros

View File

@ -84,8 +84,15 @@ export class CustomWrapperGenerator {
let out = '';
// Check
if (!structuresWithVTableAddress.includes(this.#struct.name)) {
throw new Error('Generating A Custom Wrapper Requires The VTable Address To Be Specified');
const checks: { name: string, value: boolean }[] = [
{name: 'VTable Address', value: structuresWithVTableAddress.includes(this.#struct.name)},
{name: 'VTable Size', value: this.#struct.getVTable().hasSize()},
{name: 'Structure Size', value: this.#struct.hasSize()}
];
for (const check of checks) {
if (!check.value) {
throw new Error('Generating A Custom Wrapper Requires The ' + check.name + ' To Be Specified');
}
}
// Structure

View File

@ -117,6 +117,9 @@ export class Struct {
}
return out;
}
hasSize() {
return !!this.#size;
}
// Generate Properties
#generateProperties() {
@ -206,15 +209,15 @@ export class Struct {
}
}
}
out += '#endif\n';
// Allocation Method
if (this.#size !== null) {
if (this.hasSize()) {
// THIS DOES NOT CONSTRUCT THE OBJECT
out += `${INDENT}static ${this.name} *allocate() {\n`;
out += `${INDENT}${INDENT}return (${this.name} *) ::operator new(sizeof(${this.name}));\n`;
out += `${INDENT}static ${this.name} *allocate(const size_t extra = 0) {\n`;
out += `${INDENT}${INDENT}return (${this.name} *) ::operator new(sizeof(${this.name}) + extra);\n`;
out += `${INDENT}}\n`;
}
// Return
out += '#endif\n';
return out;
}

View File

@ -74,6 +74,9 @@ export class VTable {
}
}
}
hasSize() {
return !!this.#size;
}
// Get Full Methods Table
getMethods(includeDestructors = true) {
@ -154,7 +157,7 @@ export class VTable {
out += `${INDENT}void *${INTERNAL}unknown${i.toString()};\n`;
}
}
if (this.#size === null) {
if (!this.hasSize()) {
// Prevent Construction
out += preventConstruction(this.getName());
}