From 91b20bc366d3f48fc69829911fa47e4ebb196b58 Mon Sep 17 00:00:00 2001 From: Richard Thier Date: Fri, 25 Apr 2025 00:05:39 +0200 Subject: [PATCH] refactor this with self + add c++ compat --- array_handle_test.c | 6 +++--- handle.h | 43 ++++++++++++++++++++++++++++++++++--------- handle_test.c | 6 +++--- makefile | 2 ++ 4 files changed, 42 insertions(+), 15 deletions(-) diff --git a/array_handle_test.c b/array_handle_test.c index ba470ab..6aaaea1 100644 --- a/array_handle_test.c +++ b/array_handle_test.c @@ -7,10 +7,10 @@ struct Vektor { int *v; }; handle(Vektor) { if(state == HANDLE_CREAT) { - this->count = *(int*) data; - this->v = calloc(this->count, sizeof(int)); + self->count = *(int*) data; + self->v = (int*) calloc(self->count, sizeof(int)); } else if (state == HANDLE_DESTR){ - if(this->v) free(this->v); + if(self->v) free(self->v); } } diff --git a/handle.h b/handle.h index b61c2d5..9b0b0f0 100644 --- a/handle.h +++ b/handle.h @@ -1,9 +1,6 @@ #ifndef MAG_HANDLE_H #define MAG_HANDLE_H - -#ifdef __cplusplus -#error "handle.h does not work with C++ compilers, you must compile these files with GCC directly!" -#endif +/* Simple single-header library that makes you have RAII in gcc (also works in C++ compilers) */ /** Tells your constructor/destructor handler function about the state */ enum HANDLE_STATE { @@ -11,6 +8,8 @@ enum HANDLE_STATE { HANDLE_DESTR }; +#ifndef __cplusplus + #define creat(TNAME, VNAME, VINIT) \ [[gnu::always_inline]] inline void VNAME##_cleanuper(struct TNAME *v) { \ TNAME##_lifetime_handler(HANDLE_DESTR, v, NULL); \ @@ -21,8 +20,34 @@ enum HANDLE_STATE { #define handle(TNAME) \ static inline void TNAME##_lifetime_handler( \ enum HANDLE_STATE state, \ - struct TNAME *this, \ + struct TNAME *self, \ void *data) + +#else /* C++ compilers better be able to compile code written with us */ + +#define creat(TNAME, VNAME, VINIT) \ + TNAME##_raiicpp VNAME(VINIT); + +#define handle(TNAME) \ + struct TNAME##_raiicpp; \ + static inline void TNAME##_lifetime_handler( \ + enum HANDLE_STATE state, \ + struct TNAME##_raiicpp *self, \ + void *data); \ + struct TNAME##_raiicpp : public TNAME { \ + inline TNAME##_raiicpp(void *data) { \ + TNAME##_lifetime_handler(HANDLE_CREAT, this, data); \ + } \ + inline ~TNAME##_raiicpp() { \ + TNAME##_lifetime_handler(HANDLE_DESTR, this, nullptr); \ + } \ + }; \ + static inline void TNAME##_lifetime_handler( \ + enum HANDLE_STATE state, \ + struct TNAME##_raiicpp *self, \ + void *data) + +#endif /* __cplusplus */ /* * EXAMPLE: * @@ -34,10 +59,10 @@ enum HANDLE_STATE { * * handle(Meaning) { * if(state == HANDLE_CREAT) { - * this->a = *(int*) data; - * this->b = 2; + * self->a = *(int*) data; + * self->b = 2; * } else { - * printf("%d\n", this->a + this->b); + * printf("%d\n", self->a + self->b); * } * } * @@ -50,4 +75,4 @@ enum HANDLE_STATE { * * Rem.: Unrelated trick, but you can typedef struct A A; // both typedef and forward declare */ -#endif // MAG_HANDLE_H +#endif /* MAG_HANDLE_H */ diff --git a/handle_test.c b/handle_test.c index 4e0850a..c7a0e2a 100644 --- a/handle_test.c +++ b/handle_test.c @@ -8,11 +8,11 @@ struct Meaning { handle(Meaning) { if(state == HANDLE_CREAT) { - this->a = *(int*) data; - this->b = 2; + self->a = *(int*) data; + self->b = 2; } else { // Destructor - printf("%d\n", this->a + this->b); + printf("%d\n", self->a + self->b); } } diff --git a/makefile b/makefile index d8b8932..207de49 100644 --- a/makefile +++ b/makefile @@ -8,6 +8,8 @@ gcc: gcc raii_test.c -o raii_test g++ raii_test.cpp -o raii_test_cpp gcc handle_test.c -o handle_test + gcc array_handle_test.c -o array_handle_test + g++ array_handle_test.c -o array_handle_test_gpp clang: clang macroname.c -o macroname clang count.c -o count