digitalmars.D.announce - Automatic translation from .h -> .d using nothing but CTFE!
- Robert Fraser <fraserofthenight gmail.com> Jun 12 2009
- Robert Fraser <fraserofthenight gmail.com> Jun 12 2009
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
There was a convo a while back about using the import expression and
CTFE/templates to automatically convert C/C++ .h files to .d files
without requiring an external program like bcd.gen or htod... Well, I
had a need for just such a thing, so I wrote a quick one up (that will
only work if you've written the header file in a special format). I
attached the relevant code, if you understand what's going on, you could
probably modify it. This isn't a "release" of anything, since it has no
comments, etc., but just an interesting proof-of-concept.
This D code:
mixin(sharedFromHeader_mixin!("platif.h")(LIB_NAME));
Generates the contents of the attached "formatted.d" (except not
formatted, obviously :-)).
Basically, you need this macro in your C++ header:
#define FUN(__NAME__, __RV__, __PARAMS__) __RV__ __NAME__ __PARAMS__
You'll also want to redefine some types like so:
#define _CONST const
#define _VOID void
#define _LINT long // int masquerading as a long
#define _LUINT unsigned long
#define _INT int
#define _UINT unsigned int
#define _LONG __int64
#define _ULONG unsigned __int64
#define _CHAR char
To add new types to the D conversion function, see the convertCppTypes
in sharedlib.d
Then anything you want copied directly into the D file, you need to wrap
in // COPY and // END:
// COPY
struct MofIf
{
_INT (*Stream_New)(_VOID**);
_INT (*Stream_Read)(_VOID*, _VOID*, _LUINT, _LUINT*);
_INT (*Stream_Seek)(_VOID*, _ULONG);
_INT (*Stream_Tell)(_VOID*, _ULONG*);
_INT (*Stream_GetSize)(_VOID*, _ULONG*);
_INT (*Stream_GetAvailable)(_VOID*, _ULONG*);
};
// END
Then write your functions in an // FUNCTION // END block:
// FUNCTIONS
FUN(initMof, _VOID, (MofIf* _mof));
FUN(mimeOnFire, _INT, (_CONST _CHAR* path));
// END
Anything in the header outside those blocks will be ignored. Also the
syntax is extremely specific, so the line must start with "FUN(" and end
with ");" without spaces (you can have comments after that).
Be warned, though -- compile times are SLOOW, even with only two
functions :-). I just started this part of the project, so when there's
the 70+ I expect to have when it's done... uh oh. A better replace
function could solve this (anyone have a good CTFE replace function
sitting around? :-P)
There's also a simpler function used to wrap dynamic libraries. It's
used like:
mixin(shared_mixin(LIB_NAME, [
"int function(char*)", "mimeOnFire",
"void function(MofIf*)", "initMof"]));
which will generate function pointers for all the functions and
"_loadLib()" and "_unloadLib()" functions which load the library, look
up the symbols, etc. The header function actually calls this one, but
you could easily modify it to toss out declarations for a static library
as well.
Enjoy! Big thanks to Ary for Descent's CTFE debugger; this took 45
minutes instead of 3 hours thanks to that!
(License : Public Domain)
Jun 12 2009
Robert Fraser wrote:[...]
BTW, the code is D1+Tango... it shouldn't be overly hard to port, though, since the only part of Tango it uses is tango.sys.SharedLibrary. As for D2, change char[] to string, and all should be good.
Jun 12 2009








Robert Fraser <fraserofthenight gmail.com>