digitalmars.D.learn - Interfacing with C libs: weeding through C/C++ macros and such in
- Alec Stewart (50/50) Jan 13 2019 Hello all!
- Alex (18/61) Jan 13 2019 These three are members of the standard library in D.
- Alec Stewart (6/17) Jan 13 2019 That would make it easier because there's a lot of preprocessor
- Mike Parker (12/28) Jan 13 2019 Generally this is done to allow the compile-time configuration of
Hello all! So while I have a decent grasp on D, I've been having trouble figuring out specific projects that I could do in D, so I thought I'd maybe find a little C or C++ library I could transfer over to D. I decided to make my life easier and look for something that's just a single header file, and while that does make things easier there are a TON of macros and inline functions that it almost seems ridiculous and it's somewhat overwhelming. Example without code; for some reason a macro is defined for the stdlib functions `malloc`, `realloc`, and `free`. Maybe it's just because I don't have any pro experience with C or C++, but that seems a bit excessive. Or I could just be dumb. Example with code (because I need help figuring out how whether I even need this or not): #ifndef RS_API #ifdef RS_NOINLINE /* GCC version 3.1 required for the no inline attribute. */ #if RS_GCC_VERSION > 30100 #define RS_API static __attribute__((noinline)) #elif defined(_MSC_VER) #define RS_API static __declspec(noinline) #else #define RS_API static #endif #elif RS_C99 #define RS_API static inline #elif defined(__GNUC__) #define RS_API static __inline__ #elif defined(_MSC_VER) #define RS_API static __forceinline #else #define RS_API static #endif #endif I understand what it's doing, but do I really any of this with D? And then there's this inline function #define RS_DATA_SIZE(f, s, input) \ do { \ if (rs_is_heap(input)) \ f(s, input->heap.buffer, rs_heap_len(input)); \ else \ f(s, input->stack.buffer, rs_stack_len(input)); \ } while (0) so yea. There's a little over 300 lines of preprocessor stuff. My question is how you all determine what to carry over from C libs in terms of preprocessor stuff. I imagine most useful values everyone just makes an enum for, and structs and unions are kept. Thanks for any help you give!
Jan 13 2019
On Sunday, 13 January 2019 at 22:40:57 UTC, Alec Stewart wrote:Example without code; for some reason a macro is defined for the stdlib functions `malloc`, `realloc`, and `free`. Maybe it's just because I don't have any pro experience with C or C++, but that seems a bit excessive. Or I could just be dumb.These three are members of the standard library in D. https://dlang.org/phobos/core_memory.htmlExample with code (because I need help figuring out how whether I even need this or not): #ifndef RS_API #ifdef RS_NOINLINE /* GCC version 3.1 required for the no inline attribute. */ #if RS_GCC_VERSION > 30100 #define RS_API static __attribute__((noinline)) #elif defined(_MSC_VER) #define RS_API static __declspec(noinline) #else #define RS_API static #endif #elif RS_C99 #define RS_API static inline #elif defined(__GNUC__) #define RS_API static __inline__ #elif defined(_MSC_VER) #define RS_API static __forceinline #else #define RS_API static #endif #endif I understand what it's doing, but do I really any of this with D? And then there's this inline function #define RS_DATA_SIZE(f, s, input) \ do { \ if (rs_is_heap(input)) \ f(s, input->heap.buffer, rs_heap_len(input)); \ else \ f(s, input->stack.buffer, rs_stack_len(input)); \ } while (0) so yea. There's a little over 300 lines of preprocessor stuff. My question is how you all determine what to carry over from C libs in terms of preprocessor stuff. I imagine most useful values everyone just makes an enum for, and structs and unions are kept. Thanks for any help you give!At first, I would suggest to try out some automatic converters, which are written by the community: https://wiki.dlang.org/Bindings#Binding_generators especially dstep and dpp I had some ambivalent experience with the procedure of converting C --> D, but there is C code out there, which behaves very well in this respect... So, generally, I pursued the tactics of automatic conversion trying to compile rewriting missing parts. Also, if there is a possibility to compile the C/C++ library, you could provide the interface only to the functions you need. Then, you reuse the existent code directly and interface the library by declaring the interfaces as extern in your D sources. https://dlang.org/spec/attribute.html#linkage
Jan 13 2019
On Sunday, 13 January 2019 at 23:23:50 UTC, Alex wrote:These three are members of the standard library in D. https://dlang.org/phobos/core_memory.htmlAh, yea that's way easier.At first, I would suggest to try out some automatic converters, which are written by the community: https://wiki.dlang.org/Bindings#Binding_generators especially dstep and dppThat would make it easier because there's a lot of preprocessor stuff that ends up being circular references if I use `enum` or `const`.Also, if there is a possibility to compile the C/C++ library, you could provide the interface only to the functions you need. Then, you reuse the existent code directly and interface the library by declaring the interfaces as extern in your D sources. https://dlang.org/spec/attribute.html#linkageThat would also be easier. :P Thanks!
Jan 13 2019
On Sunday, 13 January 2019 at 22:40:57 UTC, Alec Stewart wrote:Example without code; for some reason a macro is defined for the stdlib functions `malloc`, `realloc`, and `free`. Maybe it's just because I don't have any pro experience with C or C++, but that seems a bit excessive. Or I could just be dumb.Generally this is done to allow the compile-time configuration of memory allcoators. Back in my C days I had a little memory module that tracked total allocated and unallocated bytes and logged a few stats to a file at shutdown. I used macros to switch between it and the default stdlib calls.I understand what it's doing, but do I really any of this with D?No.And then there's this inline function #define RS_DATA_SIZE(f, s, input) \ do { \ if (rs_is_heap(input)) \ f(s, input->heap.buffer, rs_heap_len(input)); \ else \ f(s, input->stack.buffer, rs_stack_len(input)); \ } while (0)Generally, this sort of thing can be moved into a D function or template if it's repeated in several places. Without the do...while, of course. And in case you're unfamiliar with its purpose here: https://stackoverflow.com/questions/154136/why-use-apparently-meaningless-do-while-and-if-else-statements-in-macros
Jan 13 2019