digitalmars.D.announce - Automatic translation from .h -> .d using nothing but CTFE!
- Robert Fraser (65/65) Jun 12 2009 There was a convo a while back about using the import expression and
- Robert Fraser (4/5) Jun 12 2009 BTW, the code is D1+Tango... it shouldn't be overly hard to port,
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