www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - C to D: please help translate this weird macro

reply Ki Rill <rill.ki yahoo.com> writes:
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).
Sep 20 2023
next sibling parent reply Ki Rill <rill.ki yahoo.com> writes:
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)) ```
Sep 20 2023
next sibling parent Dejan Lekic <dejan.lekic gmail.com> writes:
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
Sep 20 2023
prev sibling parent reply Dejan Lekic <dejan.lekic gmail.com> writes:
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
Sep 20 2023
parent reply Ki Rill <rill.ki yahoo.com> writes:
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.
Sep 20 2023
parent reply Ki Rill <rill.ki yahoo.com> writes:
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))); } ```
Sep 20 2023
parent reply Nick Treleaven <nick geany.org> writes:
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)
Sep 21 2023
next sibling parent Nick Treleaven <nick geany.org> writes:
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);
Sep 21 2023
prev sibling next sibling parent user1234 <user1234 12.de> writes:
On Thursday, 21 September 2023 at 16:28:25 UTC, Nick Treleaven 
wrote:
 (Untested)
There might be a `need this` error
Sep 21 2023
prev sibling parent Ki Rill <rill.ki yahoo.com> writes:
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:)
Sep 22 2023
prev sibling next sibling parent ryuukk_ <ryuukk.dev gmail.com> writes:
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/
Sep 20 2023
prev sibling next sibling parent reply Imperatorn <johan_forsberg_86 hotmail.com> writes:
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?
Sep 21 2023
parent Ki Rill <rill.ki yahoo.com> writes:
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.
Sep 22 2023
prev sibling parent Ki Rill <rill.ki yahoo.com> writes:
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.
Sep 23 2023