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

View File

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

View File

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

View File

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

View File

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