David L. Davis 
| In adding functions to my Financial project, and ran along a problem using a "..." parameter in a Windows' DLL. The function real npv( in real rRate, ... ) works fine in a .exe build, but not as a exported function in a DLL build. So I was wondering, if any one else has ran across this problem, and that maybe there's a better to do this...or is this an error in which case I should report this a an error to Walter?
Many thanks in advance! :))
Below is the command-line used to compile and run the test code, there aren't any errors displaying...but the npv() function returns a zero. Also I've added all the test code (npv.d, npv.def, and loader.d) below.
Command-line: Compiling and running the test code below
-------------------------------------------------------
C:\dmd>bin\dmd npv.d npv.def
C:\dmd\bin\..\..\dm\bin\link.exe npv,,,user32+kernel32,npv.def/noi;
C:\dmd>bin\dmd loader.d
C:\dmd\bin\..\..\dm\bin\link.exe loader,,,user32+kernel32/noi;
C:\dmd>loader
sLibName="C:\dmd\npv.dll", hLibWithDLL=268435456
"C:\dmd\npv.dll" is loaded
npv's dll hex addry=10003060, Testing npv( 0.1, -10_000, 3_000, 4_200, 6_800 )= 0.00, ans=$1,188.44
sln's dll hex addry=100033AC, Testing sln( 30000, 7500, 10 )=2250.00, ans=$2,250.00
"C:\dmd\npv.dll" is unloaded
C:\dmd>
# // -- npv.d starts --
# // npv.d - npv.dll test function call with a "..." parameter
# // To compile: C:\dmd>bin\dmd npv.d npv.def
# // Creates npv.dll
# private import std.math;
# private import std.c.windows.windows;
#
# extern( C )
# {
# void gc_init();
# void gc_term();
# void _minit();
# void _moduleCtor();
# void _moduleUnitTests();
# }
#
# extern( Windows )
# BOOL DllMain
# (
# HINSTANCE hInstance,
# ULONG ulReason,
# LPVOID pvReserved
# )
# {
# switch( ulReason )
# {
# case DLL_PROCESS_ATTACH:
# gc_init(); // initialize GC
# _minit(); // initialize module list
# _moduleCtor(); // run module constructors
# _moduleUnitTests(); // run module unit tests
# break;
#
# case DLL_PROCESS_DETACH:
# gc_term(); // shut-down the GC
# break;
#
# case DLL_THREAD_ATTACH:
# DLL_THREAD_DETACH:
# // Multiple threads not supported yet
# break;
# }
#
# return true;
# }
#
# /+
# ' NPV - Net Present Value.
# ' -------------------------------------------
# ' Excel/VBA: npv( Rate, Value1, Value2, ... )
# +/
# extern( D )
# export real npv( in real rRate, ... )
# {
# real[] rValues;
# real rSum = 0.0;
# uint uiy;
#
# rValues.length = _arguments.length;
#
# for ( uint uix = 0; uix < _arguments.length; uix++)
# {
# if ( _arguments[ uix ] == typeid( real ) )
# {
# rValues[ uix ] = *cast( real * )_argptr;
# _argptr += real.sizeof;
# }
# else if ( _arguments[ uix ] == typeid( double ) )
# {
# rValues[ uix ] = *cast( double * )_argptr;
# _argptr += double.sizeof;
# }
# else if ( _arguments[ uix ] == typeid( float ) )
# {
# rValues[ uix ] = *cast( float * )_argptr;
# _argptr += float.sizeof;
# }
# else if ( _arguments[ uix ] == typeid( long ) )
# {
# rValues[ uix ] = *cast( long * )_argptr;
# _argptr += long.sizeof;
# }
# else if ( _arguments[ uix ] == typeid( int ) )
# {
# rValues[ uix ] = *cast( int * )_argptr;
# _argptr += int.sizeof;
# }
# else if ( _arguments[ uix ] == typeid( ulong ) )
# {
# rValues[ uix ] = *cast( ulong * )_argptr;
# _argptr += ulong.sizeof;
# }
# else if ( _arguments[ uix ] == typeid( uint ) )
# {
# rValues[ uix ] = *cast( uint * )_argptr;
# _argptr += uint.sizeof;
# }
# }
#
# uiy = rValues.length - 1;
# rSum = 0.0;
#
# for ( uint uix = 0; uix < rValues.length; uix++ )
# {
# rSum += ( rValues[ uix ] /
# std.math.pow( 1 + rRate, rValues.length - uiy ) );
# uiy--;
# }
#
# return rSum;
#
# } // end real npv( in real, ... )
#
# /+
# ' SLN - Straight-Line Depreciation.
# ' --------------------------------------
# ' Excel/VBA: sln( Cost, Salvage, Life )
# +/
# extern( D )
# export real sln
# (
# in real rCost,
# in real rSalvage,
# in real rLife
# )
# {
# return ( rCost - rSalvage ) / rLife;
#
# } // end sln( in real, in real, in real )
# // -- npv.d ends --
# ; -- npv.def starts --
# LIBRARY npv
# DESCRIPTION 'test def for the npv call in a DLL'
#
# EXETYPE NT
# SUBSYSTEM WINDOWS
# CODE PRELOAD DISCARDABLE
# DATA PRELOAD SINGLE
#
# EXPORTS
# ; -- npv.def ends --
# // -- loader.d starts --
# // loader.d - DLL Loader Code
# // To compile: C:\dmd>bin\dmd loader.d
# // Creates loader.exe
# import std.stdio;
# import std.c.windows.windows;
#
# typedef real ( *pfn_npv )( in real, ... );
# typedef real ( *pfn_sln )( in real, in real, in real );
#
# int main( in char[][] args )
# {
# HINSTANCE hLibWinDLL = null;
# char[] sLibName = ""; //r"C:\dmd\npv.dll";
# char[] sPath = "";
#
# /+
# ' Set sPath to the Drive and Directory path of
# ' the executeable that is running.
# '
# ' (for example: if args[ 0 ] == "C:\dmd\loader.exe"
# ' then sPath == r"C:\dmd")
# +/
# sPath = args[0][ 0 .. std.string.rfind( args[ 0 ], r"\" ) ].dup;
# sLibName = sPath ~ r"\npv.dll";
#
# hLibWinDLL = LoadLibraryA( std.string.toStringz( sLibName ) );
# writefln("sLibName=\"%s\", hLibWithDLL=%d",
# sLibName, cast(int)hLibWinDLL );
#
# if ( hLibWinDLL <= cast(HINSTANCE)0)
# {
# writefln( "\"%s\" not found!", sLibName );
# hLibWinDLL = null;
#
# return -1;
# }
#
# writefln("\"%s\" is loaded", sLibName );
#
# pfn_npv npv =
# cast(pfn_npv)GetProcAddress( hLibWinDLL, "D3npv3npvFeYe" );
# writefln( "npv's dll hex addry=%X,
# Testing npv( 0.1, -10_000, 3_000, 4_200, 6_800 )=%5.2f, ans=$1,188.44",
# cast(long)npv, npv( 0.1, -10_000, 3_000, 4_200, 6_800 ) );
#
# pfn_sln sln =
# cast(pfn_sln)GetProcAddress( hLibWinDLL, "D3npv3slnFeeeZe" );
# writefln( "sln's dll hex addry=%X,
# Testing sln( 30000, 7500, 10 )=%5.2f, ans=$2,250.00",
# cast(long)sln, sln( 30000, 7500, 10 ) );
#
# writefln("\"%s\" is unloaded", sLibName );
#
# FreeLibrary( hLibWinDLL );
#
# return 0;
#
# } // end int main()
# // -- loader.d ends --
David L.
-------------------------------------------------------------------
"Dare to reach for the Stars...Dare to Dream, Build, and Achieve!"
|