|
Archives
D Programming
digitalmars.Ddigitalmars.D.bugs digitalmars.D.dtl digitalmars.D.ide digitalmars.D.dwt digitalmars.D.announce digitalmars.D.learn digitalmars.D.debugger D.gnu D C/C++ Programming
c++c++.announce c++.atl c++.beta c++.chat c++.command-line c++.dos c++.dos.16-bits c++.dos.32-bits c++.idde c++.mfc c++.rtl c++.stl c++.stl.hp c++.stl.port c++.stl.sgi c++.stlsoft c++.windows c++.windows.16-bits c++.windows.32-bits c++.wxwindows digitalmars.empire digitalmars.DMDScript electronics |
digitalmars.D.announce - Automatic translation from .h -> .d using nothing but CTFE!
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:[...] Jun 12 2009
|