www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Interfacing with C libs: weeding through C/C++ macros and such in

reply Alec Stewart <alec-stewart protonmail.com> writes:
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
next sibling parent reply Alex <sascha.orlov gmail.com> writes:
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.html
 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!
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
parent Alec Stewart <alec-stewart protonmail.com> writes:
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.html
Ah, 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 dpp
That 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#linkage
That would also be easier. :P Thanks!
Jan 13
prev sibling parent Mike Parker <aldacron gmail.com> writes:
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