digitalmars.D - Using the C preprocessor with D code
- H. S. Teoh via Digitalmars-d (67/67) Apr 05 2017 D doesn't have a preprocessor, and for good reason, as it can allow all
- Walter Bright (3/4) Apr 05 2017 There are some issues with it. The C preprocessor is defined to work on
- H. S. Teoh via Digitalmars-d (10/15) Apr 05 2017 Well, yes, but since D syntax is sufficiently close to C, the difference
- Patrick Schluter (8/13) Apr 06 2017 I did this kind of things in the '90s with 2 very different
D doesn't have a preprocessor, and for good reason, as it can allow all sorts of hard-to-find bugs and other issues that make code hard to maintain / understand. However, some time ago I found an occasion where it was useful to run D code through a C preprocessor before handing it to the D compiler. This is in the context of a wrapper I wrote around libfreetype for one of my projects. It was easy enough to write declarations for Freetype functions that I needed (I didn't intend for the wrapper to be *complete*; just good enough for what I need), but when it came to handling Freetype errors, I didn't want to manually type in error definitions (which may change upon upgrading libfreetype). Fortunately, Freetype itself comes with a flexible error-handling module in the form of the header file fterrdef.h, in which errors are defined as macros of the form FT_ERRORDEF_(name,code,msg) and FT_NOERRORDEC_(name,code,msg). By suitably defining these two macros and #include'ing the file, the user can generate useful things like tables of error messages, switch statement blocks for handling translating error codes, etc.. Of course, that's in the realm of C code, but since the C preprocessor actually doesn't care what language it's processing (all it really cares it's actually possible to do this *directly from D code*. So here's what I did: ------------------------------------snip----------------------------------- module font.freetype_errors; alias FT_Error = int; /* This sets up the macros for extracting the error definitions */ #define FT_ERRORDEF_(name,code,msg) \ #define FT_NOERRORDEF_(name,code,msg) \ /* This (evil!) magic does the actual emitting of the enum declaration */ #include "freetype2/freetype/fterrdef.h" #undef FT_ERRORDEF_ #undef FT_NOERRORDEF_ string toString(FT_Error err) { switch (err) { /* This sets up the macros for extracting the error messages */ #define FT_ERRORDEF_(name,code,msg) \ return msg; #define FT_NOERRORDEF_(name,code,msg) \ return msg; #include "freetype2/freetype/fterrdef.h" default: import std.conv : to; return "Freetype error " ~ to!string(cast(int)err); } } ------------------------------------snip----------------------------------- The D compiler, of course, can't compile this code, because it doesn't running it through cpp and piping the output to an actual .d file that will be imported by the rest of my code. The preprocessor does the work of actually expanding those error definitions into a D-style enum, as well as generate the body of a nice function for converting FT_Error into an error message defined by the libfreeetype sources. Since this is automatically done, I don't even have to change the code when upgrading to a new version of libfreetype; any new error definitions will automatically be created for me. :-) Who says you can't use a preprocessor with D code? ;-) T -- Let's not fight disease by killing the patient. -- Sean 'Shaleh' Perry
Apr 05 2017
On 4/5/2017 1:50 PM, H. S. Teoh via Digitalmars-d wrote:Who says you can't use a preprocessor with D code? ;-)There are some issues with it. The C preprocessor is defined to work on "preprocessor tokens", which are not quite the same thing as text.
Apr 05 2017
On Wed, Apr 05, 2017 at 06:21:48PM -0700, Walter Bright via Digitalmars-d wrote:On 4/5/2017 1:50 PM, H. S. Teoh via Digitalmars-d wrote:Well, yes, but since D syntax is sufficiently close to C, the difference is immaterial. :-) Mostly, anyway. I can see the preprocessor getting confused by D-specific syntax like token strings or `` literals, but for the most part if the purpose is to expand C macros into D code snippets, this mostly shouldn't matter. T -- Не дорог подарок, дорога любовь.Who says you can't use a preprocessor with D code? ;-)There are some issues with it. The C preprocessor is defined to work on "preprocessor tokens", which are not quite the same thing as text.
Apr 05 2017
On Thursday, 6 April 2017 at 01:21:48 UTC, Walter Bright wrote:On 4/5/2017 1:50 PM, H. S. Teoh via Digitalmars-d wrote:I did this kind of things in the '90s with 2 very different languages AutoLISP and Foxbase. Worked really well and allowed to avoid a lot of code duplication. These 2 languages were very deficient when speaking about modularity and global symbols of a project. There were really only 2 or 3 small things that couldn't be used with the macros. Syntactically D is much, much closer to C than Lisp or dBase language.Who says you can't use a preprocessor with D code? ;-)There are some issues with it. The C preprocessor is defined to work on "preprocessor tokens", which are not quite the same thing as text.
Apr 06 2017