Re: C to D: please help translate this weird macro
On Wednesday, 20 September 2023 at 13:53:08 UTC, Ki Rill wrote: Here is the macro: ```C #define NK_CONTAINER_OF(ptr,type,member)\ (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member))) ``` I'm trying to translate the Nuklear GUI library to D [here](https://github.com/rillki/nuklear-d/tree/nuklear-d-translation). I did translate the library. Wow! That was a lot. It successfully builds, but does not work for long and crashes if I try to do something: it's either an assertion that fails or out of bounds array access is thrown by D. The only thing that works is pressing a button. Now I need to somehow find and fix these things. Nuclear uses flexible array members in structs and I am a bit puzzled how to handle this without a major code refactor.
Re: C to D: please help translate this weird macro
On Thursday, 21 September 2023 at 16:50:51 UTC, Imperatorn wrote: On Wednesday, 20 September 2023 at 13:53:08 UTC, Ki Rill wrote: Here is the macro: ```C #define NK_CONTAINER_OF(ptr,type,member)\ (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member))) ``` I'm trying to translate the Nuklear GUI library to D [here](https://github.com/rillki/nuklear-d/tree/nuklear-d-translation). When you're done, will you put it on dub? Yes, I will.
Re: C to D: please help translate this weird macro
On Thursday, 21 September 2023 at 16:28:25 UTC, Nick Treleaven wrote: The 1st argument of `getMember` can just be T, like the original macro. The 2nd argument needs to be a compile-time string. Also the `char*` cast needs to apply to `ptr` before subtracting the offset AFAICS. So reordering to keep type inference of `ptr`: ```d auto nk_container_of(T, string member, P)(P ptr) { return cast(T*)(cast(void*)(cast(char*)ptr - __traits(getMember, T, member).offsetof))); } ``` (Untested) I will test it:)
Re: C to D: please help translate this weird macro
On Wednesday, 20 September 2023 at 13:53:08 UTC, Ki Rill wrote: Here is the macro: ```C #define NK_CONTAINER_OF(ptr,type,member)\ (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member))) ``` I'm trying to translate the Nuklear GUI library to D [here](https://github.com/rillki/nuklear-d/tree/nuklear-d-translation). When you're done, will you put it on dub?
Re: C to D: please help translate this weird macro
On Thursday, 21 September 2023 at 16:28:25 UTC, Nick Treleaven wrote: (Untested) There might be a `need this` error
Re: C to D: please help translate this weird macro
On Thursday, 21 September 2023 at 16:28:25 UTC, Nick Treleaven wrote: return cast(T*)(cast(void*)(cast(char*)ptr - __traits(getMember, T, member).offsetof))); There's a trailing `)` that needs removing. Also pretty sure it can be simplified to: return cast(T*)(cast(char*)ptr - __traits(getMember, T, member).offsetof);
Re: C to D: please help translate this weird macro
On Thursday, 21 September 2023 at 02:57:07 UTC, Ki Rill wrote: On Thursday, 21 September 2023 at 02:23:32 UTC, Ki Rill wrote: wrote: [...] Translated it to this eventually: ```D auto nk_container_of(P, T)(P ptr, T type, const(char)* member) { return cast(T*)(cast(void*)(cast(char*) (ptr - __traits(getMember, type, member).offsetof))); } ``` The 1st argument of `getMember` can just be T, like the original macro. The 2nd argument needs to be a compile-time string. Also the `char*` cast needs to apply to `ptr` before subtracting the offset AFAICS. So reordering to keep type inference of `ptr`: ```d auto nk_container_of(T, string member, P)(P ptr) { return cast(T*)(cast(void*)(cast(char*)ptr - __traits(getMember, T, member).offsetof))); } ``` (Untested)
Re: C to D: please help translate this weird macro
On Thursday, 21 September 2023 at 02:23:32 UTC, Ki Rill wrote: wrote: [...] Translated it to this eventually: ```D auto nk_container_of(P, T)(P ptr, T type, const(char)* member) { return cast(T*)(cast(void*)(cast(char*) (ptr - __traits(getMember, type, member).offsetof))); } ```
Re: C to D: please help translate this weird macro
On Wednesday, 20 September 2023 at 17:14:41 UTC, Dejan Lekic wrote: [...] NK_CONTAINER_OF should probably be translated to: `cast(T*)((cast(void*)ptr - __traits(getMember, T, member).offsetof))` PS. I did not invent this. My original idea was far worse than this. - It was suggested on IRC by a much cleverer D programmer than myself - Herringway@IRC Thanks! I translated it to this originally after looking at the links you've provided: ```D auto nk_container_of(P, T)(P ptr, T type, size_t member_offsetof) { return cast(T*)(cast(void*)(cast(char*)(1 ? (ptr) : ptr - member_offsetof))); } ``` `cast(T*)((cast(void*)ptr - __traits(getMember, T, member).offsetof))` Now, how should I wrap it like a macro? Template mixin? I'm not that familiar with D meta programming... I shall skim through the `D templates tutorial` for hints.
Re: C to D: please help translate this weird macro
On Wednesday, 20 September 2023 at 13:55:14 UTC, Ki Rill wrote: On Wednesday, 20 September 2023 at 13:53:08 UTC, Ki Rill wrote: Here is the macro: ```C #define NK_CONTAINER_OF(ptr,type,member)\ (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member))) ``` I'm trying to translate the Nuklear GUI library to D [here](https://github.com/rillki/nuklear-d/tree/nuklear-d-translation). Here is how `NK_OFFSETOF` is defined: ```c #define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m)) ``` NK_OFFSETOF is the same as D's struct `.offsetof` attribute. NK_CONTAINER_OF should probably be translated to: `cast(T*)((cast(void*)ptr - __traits(getMember, T, member).offsetof))` PS. I did not invent this. My original idea was far worse than this. - It was suggested on IRC by a much cleverer D programmer than myself - Herringway@IRC
Re: C to D: please help translate this weird macro
On Wednesday, 20 September 2023 at 13:53:08 UTC, Ki Rill wrote: Here is the macro: ```C #define NK_CONTAINER_OF(ptr,type,member)\ (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member))) ``` I'm trying to translate the Nuklear GUI library to D [here](https://github.com/rillki/nuklear-d/tree/nuklear-d-translation). My workflow when trying to port weird C code to D is to have a small C file, put an example code, and then run the preprocessor, and try to get how things are expanded Alternatively, latest version of visual studio allows you to see that in real time, you'll still have to write example code tho https://devblogs.microsoft.com/cppblog/visualize-macro-expansion-for-c/
Re: C to D: please help translate this weird macro
On Wednesday, 20 September 2023 at 13:55:14 UTC, Ki Rill wrote: On Wednesday, 20 September 2023 at 13:53:08 UTC, Ki Rill wrote: Here is the macro: ```C #define NK_CONTAINER_OF(ptr,type,member)\ (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member))) ``` I'm trying to translate the Nuklear GUI library to D [here](https://github.com/rillki/nuklear-d/tree/nuklear-d-translation). Here is how `NK_OFFSETOF` is defined: ```c #define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m)) ``` Looks like you are not the only one who has issue with them: https://github.com/Immediate-Mode-UI/Nuklear/issues/94 https://github.com/Immediate-Mode-UI/Nuklear/pull/309
Re: C to D: please help translate this weird macro
On Wednesday, 20 September 2023 at 13:53:08 UTC, Ki Rill wrote: Here is the macro: ```C #define NK_CONTAINER_OF(ptr,type,member)\ (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member))) ``` I'm trying to translate the Nuklear GUI library to D [here](https://github.com/rillki/nuklear-d/tree/nuklear-d-translation). Here is how `NK_OFFSETOF` is defined: ```c #define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m)) ```
C to D: please help translate this weird macro
Here is the macro: ```C #define NK_CONTAINER_OF(ptr,type,member)\ (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member))) ``` I'm trying to translate the Nuklear GUI library to D [here](https://github.com/rillki/nuklear-d/tree/nuklear-d-translation).