Thread overview
Porting OS header (from C/C++) [and dll imports]
Aug 08, 2003
Mike Wynn
Aug 08, 2003
Walter
Aug 08, 2003
Mike Wynn
Aug 26, 2003
Walter
August 08, 2003
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 ?


August 08, 2003
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 ?
>
>


August 08, 2003
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 ?
> >
> >
>
>


August 26, 2003
"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.