www.digitalmars.com         C & C++   DMDScript  

D - Porting OS header (from C/C++) [and dll imports]

reply "Mike Wynn" <mike.wynn l8night.co.uk> writes:
I've been looking through the gdiplus headers, something I was going to port
some time back.
and run across (again) the problem with D<->C interoperation

one example :
typedef enum {
    BrushTypeSolidColor = 0,
    BrushTypeHatchFill = 1,
    BrushTypeTextureFill = 2,
    BrushTypePathGradient = 3,
    BrushTypeLinearGradient = 4
} BrushType;
I have in the past just changed this toenum {
    BrushTypeSolidColor = 0,
    BrushTypeHatchFill = 1,
    BrushTypeTextureFill = 2,
    BrushTypePathGradient = 3,
    BrushTypeLinearGradient = 4
}so C code can be ported almost without change.but in my com headers I
started doingenum BrushType {
    BrushTypeSolidColor = 0,
    BrushTypeHatchFill = 1,
    BrushTypeTextureFill = 2,
    BrushTypePathGradient = 3,
    BrushTypeLinearGradient = 4
    SolidColor = 0,
    HatchFill = 1,
    TextureFill = 2,
    PathGradient = 3,
    LinearGradient = 4
}(and in some cases due to lazyness in converting the source, I added the
above method too)my personal feeling is to doenum BrushType {
    SolidColor = 0,
    HatchFill = 1,
    TextureFill = 2,
    PathGradient = 3,
    LinearGradient = 4
}version( DEPRICATED_WIN32_IDS ) {    alias BrushType.SolidColor
BrushTypeSolidColor;    alias BrushType.HatchFill BrushTypeHatchFill;
    alias BrushType.TextureFill BrushTypeTextureFill;
    alias BrushType.PathGradient BrushTypePathGradient;
    alias BrushType.LinearGradient BrushTypeLinearGradient;}is there a way
to create a dm c import lib from a dll, or will I have to do the same as I
did for winmm when I wanted timeBeginPeriod etc/// which was this ...import
winex.dynloader;alias uint MMRESULT;   /* error return code, 0 means no
error */instance DynFunc( Windows, MMRESULT, uint ) I_I_Ldr;instance
DynFunc( Windows, DWORD ) I_V_Ldr;I_I_Ldr.fp timeBeginPeriod;I_I_Ldr.fp
timeEndPeriod;I_V_Ldr.fp timeGetTime;static this(){ timeBeginPeriod =
I_I_Ldr.require( "winmm.dll", "timeBeginPeriod" ); I_I_Ldr.use(
timeEndPeriod,   "winmm.dll", "timeEndPeriod" ); I_V_Ldr.use( timeGetTime,
"winmm.dll", "timeGetTime" );}which works fine but I'd rather not be getting
all the functions from a dlland would rather not have to doinstance
DynFunc( Windows, MMRESULT, uint ) I_I_Ldr;I_I_Ldr.fp
timeBeginPeriod;extern(Windows) MMRESULT load_timeBeginPeriod( uint p )
{    timeBeginPeriod = I_I_Ldr.require( "winmm.dll", "timeBeginPeriod" );
timeBeginPeriod( p );}static this(){    timeBeginPeriod =
&load_timeBeginPeriod; // lazy load function.}
// or change I_I_Ldr.fp from a ptr to func to a delegate so I can create a
lazy load context.am I right in assuming wchar/char[] can not be used as
value types in a templatesoinstance DynFunc( Windows, "winmm.dll",
"timeGetTime", DWORD ).fp timeGetTime;would not allow the creation of a lazy
loading imported function ?
Aug 08 2003
parent reply "Walter" <walter digitalmars.com> writes:
I'm confused by your message. Could you take a look at it again please?

"Mike Wynn" <mike.wynn l8night.co.uk> wrote in message
news:bh03vs$2hgs$1 digitaldaemon.com...
 I've been looking through the gdiplus headers, something I was going to
port
 some time back.
 and run across (again) the problem with D<->C interoperation

 one example :
 typedef enum {
     BrushTypeSolidColor = 0,
     BrushTypeHatchFill = 1,
     BrushTypeTextureFill = 2,
     BrushTypePathGradient = 3,
     BrushTypeLinearGradient = 4
 } BrushType;
 I have in the past just changed this toenum {
     BrushTypeSolidColor = 0,
     BrushTypeHatchFill = 1,
     BrushTypeTextureFill = 2,
     BrushTypePathGradient = 3,
     BrushTypeLinearGradient = 4
 }so C code can be ported almost without change.but in my com headers I
 started doingenum BrushType {
     BrushTypeSolidColor = 0,
     BrushTypeHatchFill = 1,
     BrushTypeTextureFill = 2,
     BrushTypePathGradient = 3,
     BrushTypeLinearGradient = 4
     SolidColor = 0,
     HatchFill = 1,
     TextureFill = 2,
     PathGradient = 3,
     LinearGradient = 4
 }(and in some cases due to lazyness in converting the source, I added the
 above method too)my personal feeling is to doenum BrushType {
     SolidColor = 0,
     HatchFill = 1,
     TextureFill = 2,
     PathGradient = 3,
     LinearGradient = 4
 }version( DEPRICATED_WIN32_IDS ) {    alias BrushType.SolidColor
 BrushTypeSolidColor;    alias BrushType.HatchFill BrushTypeHatchFill;
     alias BrushType.TextureFill BrushTypeTextureFill;
     alias BrushType.PathGradient BrushTypePathGradient;
     alias BrushType.LinearGradient BrushTypeLinearGradient;}is there a way
 to create a dm c import lib from a dll, or will I have to do the same as I
 did for winmm when I wanted timeBeginPeriod etc/// which was this
...import
 winex.dynloader;alias uint MMRESULT;   /* error return code, 0 means no
 error */instance DynFunc( Windows, MMRESULT, uint ) I_I_Ldr;instance
 DynFunc( Windows, DWORD ) I_V_Ldr;I_I_Ldr.fp timeBeginPeriod;I_I_Ldr.fp
 timeEndPeriod;I_V_Ldr.fp timeGetTime;static this(){ timeBeginPeriod =
 I_I_Ldr.require( "winmm.dll", "timeBeginPeriod" ); I_I_Ldr.use(
 timeEndPeriod,   "winmm.dll", "timeEndPeriod" ); I_V_Ldr.use( timeGetTime,
 "winmm.dll", "timeGetTime" );}which works fine but I'd rather not be
getting
 all the functions from a dlland would rather not have to doinstance
 DynFunc( Windows, MMRESULT, uint ) I_I_Ldr;I_I_Ldr.fp
 timeBeginPeriod;extern(Windows) MMRESULT load_timeBeginPeriod( uint p )
 {    timeBeginPeriod = I_I_Ldr.require( "winmm.dll", "timeBeginPeriod" );
 timeBeginPeriod( p );}static this(){    timeBeginPeriod =
 &load_timeBeginPeriod; // lazy load function.}
 // or change I_I_Ldr.fp from a ptr to func to a delegate so I can create a
 lazy load context.am I right in assuming wchar/char[] can not be used as
 value types in a templatesoinstance DynFunc( Windows, "winmm.dll",
 "timeGetTime", DWORD ).fp timeGetTime;would not allow the creation of a
lazy
 loading imported function ?
Aug 08 2003
parent reply "Mike Wynn" <mike.wynn l8night.co.uk> writes:
it was a question about D coding style for my next porting effort ...
followed by a question about dll loading.

should the C
typedef enum {
    BrushTypeSolidColor = 0,
} BrushType;

be the D


enum : int {
    BrushTypeSolidColor = 0,
}
alias int BrushType;

or

enum BrushType : int {
    SolidColor = 0,
}
alias BrushType.SolidColor BrushTypeSolidColor;

etc ...

and the latter part was about linking to dlls, I wrote (and posted) a
dynamic linking template class
that allows me to do

instance DynFunc( Windows, DWORD ) I_V_Ldr;
I_V_Ldr.fp timeGetTime;

static this()
{
 I_V_Ldr.use( timeGetTime,     "winmm.dll", "timeGetTime" );
// or
// timeGetTime = I_V_Ldr.require(  "winmm.dll", "timeGetTime" );
}

// uses this template ...
template DynFunc( Linkage T : Linkage.Windows, R ) {
 extern ( Windows ) {
  R erf() { throw new Exception( "Shared Function not loaded" ); return
R.init; }
  typedef R (*fp)() = &erf;
 }
 instance Dyn( fp ) dynFunc;  // code to get a function of type fp from a
dll.
 alias dynFunc.use use;
 alias dynFunc.require require;
}


timeGetTime is a pointer to function (defaults to a function that throws an
exception)
I could make it a delegate to allow lazy linking (obviously you require a
context to resolve the fp)
and I can't make a template with a char[] as a value (i.e. new instance for
each functions name)
and anyway it would require a pointer to function pointer too;
I could use
template DynFunc( Linkage L : Linkage.Windows, T ) {
    typedef  T delegate( void ) fp;
    // *** NOTE THIS ^^ would be good if this could be require( dn, fn );
    ///  with a template like
/// template DynFunc( Linkage L : Linkage.Windows, T, dnt : char[], fnt :
char[] ) {
    // as in typedef T delegate(void) fp = require( dnt, fnt );
    // or  typedef T delegate(void) fp = &((new lazy_loader( dnt,
fnt )).on_first_call);

    extern(Windows) alias T(*nfp)( void );
    class lazy_loader {
        fp * to_modify;
        nfp to_call;
        char [] dllname, funcname;
        this( char[] a, char[]b ) { dllname = a; funcname =b; }
        T on_first_call( void ) {
            // loads the dll (or gets the handle from a hash table and calls
getProcAddress)
          nfp =  instance Dyn( nfp ).require( dllname, funcname );
            *to_modify = &second_call;
           return second_call();
        }
        T second_call( void ) {
           return nfp();
        }
    }
    fp require( char[] dn, char[] fn ) {
        lazy_loader ll = new lazy_loader( dn, fn );
        return &ll.on_first_call
    }
}

the benifit now is that when the module it linked you dont get 1000 function
pointer from the dll, you only get the ones that are used when they are
called.
still requires the static this { ...as I don't know how to get the fp value
initialised  }
the old method would have had to link in all the exported functions.

OR is there a way to create a D import lib from a dll ?

is that better (I've slept a little now so I think I make more sence [not
that I make sence normally]) ?

"Walter" <walter digitalmars.com> wrote in message
news:bh0t0q$8rg$2 digitaldaemon.com...
 I'm confused by your message. Could you take a look at it again please?

 "Mike Wynn" <mike.wynn l8night.co.uk> wrote in message
 news:bh03vs$2hgs$1 digitaldaemon.com...
 I've been looking through the gdiplus headers, something I was going to
port
 some time back.
 and run across (again) the problem with D<->C interoperation

 one example :
 typedef enum {
     BrushTypeSolidColor = 0,
     BrushTypeHatchFill = 1,
     BrushTypeTextureFill = 2,
     BrushTypePathGradient = 3,
     BrushTypeLinearGradient = 4
 } BrushType;
 I have in the past just changed this toenum {
     BrushTypeSolidColor = 0,
     BrushTypeHatchFill = 1,
     BrushTypeTextureFill = 2,
     BrushTypePathGradient = 3,
     BrushTypeLinearGradient = 4
 }so C code can be ported almost without change.but in my com headers I
 started doingenum BrushType {
     BrushTypeSolidColor = 0,
     BrushTypeHatchFill = 1,
     BrushTypeTextureFill = 2,
     BrushTypePathGradient = 3,
     BrushTypeLinearGradient = 4
     SolidColor = 0,
     HatchFill = 1,
     TextureFill = 2,
     PathGradient = 3,
     LinearGradient = 4
 }(and in some cases due to lazyness in converting the source, I added
the
 above method too)my personal feeling is to doenum BrushType {
     SolidColor = 0,
     HatchFill = 1,
     TextureFill = 2,
     PathGradient = 3,
     LinearGradient = 4
 }version( DEPRICATED_WIN32_IDS ) {    alias BrushType.SolidColor
 BrushTypeSolidColor;    alias BrushType.HatchFill BrushTypeHatchFill;
     alias BrushType.TextureFill BrushTypeTextureFill;
     alias BrushType.PathGradient BrushTypePathGradient;
     alias BrushType.LinearGradient BrushTypeLinearGradient;}is there a
way
 to create a dm c import lib from a dll, or will I have to do the same as
I
 did for winmm when I wanted timeBeginPeriod etc/// which was this
...import
 winex.dynloader;alias uint MMRESULT;   /* error return code, 0 means no
 error */instance DynFunc( Windows, MMRESULT, uint ) I_I_Ldr;instance
 DynFunc( Windows, DWORD ) I_V_Ldr;I_I_Ldr.fp timeBeginPeriod;I_I_Ldr.fp
 timeEndPeriod;I_V_Ldr.fp timeGetTime;static this(){ timeBeginPeriod =
 I_I_Ldr.require( "winmm.dll", "timeBeginPeriod" ); I_I_Ldr.use(
 timeEndPeriod,   "winmm.dll", "timeEndPeriod" ); I_V_Ldr.use(
timeGetTime,
 "winmm.dll", "timeGetTime" );}which works fine but I'd rather not be
getting
 all the functions from a dlland would rather not have to doinstance
 DynFunc( Windows, MMRESULT, uint ) I_I_Ldr;I_I_Ldr.fp
 timeBeginPeriod;extern(Windows) MMRESULT load_timeBeginPeriod( uint p )
 {    timeBeginPeriod = I_I_Ldr.require( "winmm.dll",
"timeBeginPeriod" );
 timeBeginPeriod( p );}static this(){    timeBeginPeriod =
 &load_timeBeginPeriod; // lazy load function.}
 // or change I_I_Ldr.fp from a ptr to func to a delegate so I can create
a
 lazy load context.am I right in assuming wchar/char[] can not be used as
 value types in a templatesoinstance DynFunc( Windows, "winmm.dll",
 "timeGetTime", DWORD ).fp timeGetTime;would not allow the creation of a
lazy
 loading imported function ?
Aug 08 2003
parent "Walter" <walter digitalmars.com> writes:
"Mike Wynn" <mike.wynn l8night.co.uk> wrote in message
news:bh1151$cpa$1 digitaldaemon.com...
 it was a question about D coding style for my next porting effort ...
 followed by a question about dll loading.

 should the C
 typedef enum {
     BrushTypeSolidColor = 0,
 } BrushType;

 be the D


 enum : int {
     BrushTypeSolidColor = 0,
 }
 alias int BrushType;

 or

 enum BrushType : int {
     SolidColor = 0,
 }
 alias BrushType.SolidColor BrushTypeSolidColor;

 etc ...
You can do either.
 and the latter part was about linking to dlls, I wrote (and posted) a
 dynamic linking template class
 that allows me to do

 instance DynFunc( Windows, DWORD ) I_V_Ldr;
 I_V_Ldr.fp timeGetTime;

 static this()
 {
  I_V_Ldr.use( timeGetTime,     "winmm.dll", "timeGetTime" );
 // or
 // timeGetTime = I_V_Ldr.require(  "winmm.dll", "timeGetTime" );
 }

 // uses this template ...
 template DynFunc( Linkage T : Linkage.Windows, R ) {
  extern ( Windows ) {
   R erf() { throw new Exception( "Shared Function not loaded" ); return
 R.init; }
   typedef R (*fp)() = &erf;
  }
  instance Dyn( fp ) dynFunc;  // code to get a function of type fp from a
 dll.
  alias dynFunc.use use;
  alias dynFunc.require require;
 }


 timeGetTime is a pointer to function (defaults to a function that throws
an
 exception)
 I could make it a delegate to allow lazy linking (obviously you require a
 context to resolve the fp)
 and I can't make a template with a char[] as a value (i.e. new instance
for
 each functions name)
 and anyway it would require a pointer to function pointer too;
 I could use
 template DynFunc( Linkage L : Linkage.Windows, T ) {
     typedef  T delegate( void ) fp;
     // *** NOTE THIS ^^ would be good if this could be require( dn, fn );
     ///  with a template like
 /// template DynFunc( Linkage L : Linkage.Windows, T, dnt : char[], fnt :
 char[] ) {
     // as in typedef T delegate(void) fp = require( dnt, fnt );
     // or  typedef T delegate(void) fp = &((new lazy_loader( dnt,
 fnt )).on_first_call);

     extern(Windows) alias T(*nfp)( void );
     class lazy_loader {
         fp * to_modify;
         nfp to_call;
         char [] dllname, funcname;
         this( char[] a, char[]b ) { dllname = a; funcname =b; }
         T on_first_call( void ) {
             // loads the dll (or gets the handle from a hash table and
calls
 getProcAddress)
           nfp =  instance Dyn( nfp ).require( dllname, funcname );
             *to_modify = &second_call;
            return second_call();
         }
         T second_call( void ) {
            return nfp();
         }
     }
     fp require( char[] dn, char[] fn ) {
         lazy_loader ll = new lazy_loader( dn, fn );
         return &ll.on_first_call
     }
 }

 the benifit now is that when the module it linked you dont get 1000
function
 pointer from the dll, you only get the ones that are used when they are
 called.
 still requires the static this { ...as I don't know how to get the fp
value
 initialised  }
 the old method would have had to link in all the exported functions.

 OR is there a way to create a D import lib from a dll ?
Just running implib on the DLL should do the trick.
Aug 26 2003