[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

My experience with a DLL



PureBytes Links

Trading Reference Links


Thanks to those who answered my recent DLL questions.  Particularly
about how to pass a float from the DLL to EasyLanguage.  The answer is
now clear.  Pass the address of an EL float variable to the DLL via
a DLL input parameter.  Then don't try to return the float by the
normal DLL function return.  Instead have the DLL write the float result
directly to that EL variable address.  It worked.

And, this opens up other possibilities.  A function can normally return
only one value.  But a number of EL variable addresses can be passed to
the DLL function and that function can write a different value to each
of those EL variables.

Below is BASIC source code for my first DLL for EasyLanguage, the T3
moving average as mentioned in my previous message.  The EL code that
calls the DLL is shown also.

If you want to know more about Power Basic, see www.powerbasic.com.
Look at their version 6.0 DLL compiler.  It consists of two compilers.
A 32 bit version and a 16 bit version.  I bought mine when they sold
them separately.  Check out their web links and forums.  There is a huge
wealth of BASIC programming information there.

I don't want to start a BASIC vs. C war (or do I), but everything I've
read on the lists over the last couple of years strongly states that
you've got to use C or C++ to code a DLL for EasyLanguage.  Well, that
myth has now been broken.  With BASIC you can code your whole DLL in one
.BAS file - not the .H, .MAK, .C, .DEF, etc. used for C.  The BASIC
compiler and all its support files fit on a 3.5" disk.  It compiles the
program below in a fraction of a second.  I haven't tried to code a DLL
for TS2000, but it is highly probable that the PowerBasic 32 bit DLL
compiler will do the job.

Lastly, some have tried to use DELPHI version 1.x (16 bit) to generate a
DLL but have not been successful.  I don't know much about DELPHI but
it has a good reputation.  Perhaps the problem has been with the DLL
function returning an incompatible FLOAT, like I had with BASIC.  In
which case, using a pointer to an EL variable location may make DELPHI
viable.

Happy DLL'ing.

' ********************************************************************
' *  ELDLL02.BAS  --  Test interface between EasyLanguage and a DLL  *
' *                   created by PowerBasic PBDLL 2.0 (16 bit).      *
' *                   By:  Barry Kaufman   Sep-23-1999               *
' ********************************************************************

' The DLL compiled from this source code can be called by a 16 bit
' version of Omega Research Tradestation or Supercharts.

' Purpose is to test the functionality of the DLL and to create a
' template for future coding of more complex functions.  This will
' show that variables can be passed, processed and then returned to
' the calling program.

' This DLL contains a function that calculates the Tillson T3
' adaptive moving average.  The T3 code is adapted from code
' posted on the "Omega List" by Bob Fulks.


' ==========================================================
'   Example Of EasyLanguage Indicator That Calls This DLL  =
' ==========================================================

' { Return a number from the DLL which is the T3 adaptive moving
'   average of price input. }

' INPUTS:

'   INDAT (C OF DATA1),   { Field and series for price. }
'   T3PER (5),            { T3 adaptive MA period. }
'   T3SMO (0.7);          { T3 MA smoothing coefficient. }

' VARS:

'   T3AVE (0);            { Output from the T3 DLL function. }

' {
'            ===== DEFINE THE DLL FUNCTIONS =====
'   T3INIT initializes DLL variables only once.  It has 2 float
'   inputs and returns a dummy integer.
'   T3CALC calculates the MA on each bar.  Inputs are 3 floats
'   and a 32 bit address for the float output.  The function
'   returns a dummy integer.
' }
' DefineDLLFunc: "C:\TEMP\ELDLL02.DLL", INT, "T3INIT", FLOAT, FLOAT;
' DefineDLLFunc: "C:\TEMP\ELDLL02.DLL", INT, "T3CALC", FLOAT, FLOAT,
'                                             FLOAT, LPFLOAT;

' IF CurrentBar = 1 THEN BEGIN
'   VALUE1 = T3INIT (T3PER, T3SMO);  { DLL will init its variables. }
' END;

' { Calculate & return T3 MA in T3AVE.  VALUE1 is dummy. }
' VALUE1 = T3CALC (INDAT, T3PER, T3SMO, &T3AVE);

' PLOT2 (T3AVE, "T3_MA");

' { End of EasyLanguage code example }


' ============================
'   DLL Compiler Directives  =
' ============================

$DEBUG PBD OFF                         ' No compile time symbolic debug.
$COMPILE DLL                           ' Compile to DLL rather than EXE.
' $HUGE                                ' Let arrays be > 64K.
$DIM ALL                               ' Declare variables before use.
$OPTION VERSION3                       ' Compatible with Windows 3.x.


' =============================
'   Declare Global Variables  =
' =============================

GLOBAL INDAT    AS SINGLE              ' Price.
GLOBAL T3PER    AS SINGLE              ' T3 period.
GLOBAL T3SMO    AS SINGLE              ' T3 smoothing coefficient.

' Working variables for the T3 MA.
GLOBAL B2        AS DOUBLE
GLOBAL B3        AS DOUBLE
GLOBAL E1        AS DOUBLE
GLOBAL E1P       AS DOUBLE             ' E1 on previous pass.
GLOBAL E2        AS DOUBLE
GLOBAL E2P       AS DOUBLE             ' E2 on previous pass.
GLOBAL E3        AS DOUBLE
GLOBAL E3P       AS DOUBLE             ' E3 on previous pass.
GLOBAL E4        AS DOUBLE
GLOBAL E4P       AS DOUBLE             ' E4 on previous pass.
GLOBAL E5        AS DOUBLE
GLOBAL E5P       AS DOUBLE             ' E5 on previous pass.
GLOBAL E6        AS DOUBLE
GLOBAL E6P       AS DOUBLE             ' E6 on previous pass.
GLOBAL C1        AS DOUBLE
GLOBAL C2        AS DOUBLE
GLOBAL C3        AS DOUBLE
GLOBAL C4        AS DOUBLE
GLOBAL F1        AS DOUBLE
GLOBAL F2        AS DOUBLE
GLOBAL T3AVE     AS DOUBLE             ' Final calculated T3 MA.

GLOBAL T3ADR     AS DWORD              ' Addr. of T3AVE in calling prog.
GLOBAL SINPTR    AS SINGLE PTR         ' Pointer for a 4 byte float.

' =====================
'   Function LibMain  =
' =====================

' Function LibMain is run once by Windows when it loads this DLL.
' This function definition is the same for any DLL.  Certain other
' run-once code can be put here as well, like initializing global
' objects.

FUNCTION LibMain (BYVAL hInstance AS INTEGER,_
                  BYVAL wDataSeg AS WORD,_
                  BYVAL wHeapSize AS WORD,_
                  lpszCmdLine AS ASCIIZ) EXPORT AS INTEGER

  LibMain = 1                          ' 1 tells WIN that load
                                       ' was a success.
END FUNCTION


' ====================
'   Function T3INIT  =
' ====================

FUNCTION T3INIT (BYVAL T3PER AS SINGLE, BYVAL T3SMO AS SINGLE)_
                EXPORT AS INTEGER

  ' Init the MA variables.
  B2 = T3SMO * T3SMO
  B3 = T3SMO * T3SMO * T3SMO
  C1 = -B3
  C2 = 3 * B2 + 3 * B3
  C3 = -6 * B2 - 3 * T3SMO - 3 * B3
  C4 = 1 + 3 * T3SMO + B3 + 3 * B2
  F1 = 2 / (T3PER + 1)
  F2 = 1 - F1

  FUNCTION = 1 ' Return a dummy integer value.

END FUNCTION


' ====================
'   Function T3CALC  =
' ====================

FUNCTION T3CALC (BYVAL INDAT AS SINGLE, BYVAL T3PER AS SINGLE,_
                BYVAL T3SMO AS SINGLE, BYVAL T3ADR AS DWORD)_
                EXPORT AS INTEGER

  ' Do the MA calculation.
  E1 = F1 * INDAT + F2 * E1P
  E2 = F1 * E1 + F2 * E2P
  E3 = F1 * E2 + F2 * E3P
  E4 = F1 * E3 + F2 * E4P
  E5 = F1 * E4 + F2 * E5P
  E6 = F1 * E5 + F2 * E6P
  T3AVE = C1 * E6 + C2 * E5 + C3 * E4 + C4 * E3

  SINPTR = T3ADR      ' Copy EL float address to pointer variable.
  @SINPTR = T3AVE     ' Send the float to the EL calling program.

  ' This is previous bar values for next pass.
  E1P = E1
  E2P = E2
  E3P = E3
  E4P = E4
  E5P = E5
  E6P = E6

  FUNCTION = 1        ' Return a dummy integer value.

END FUNCTION


' =================
'   Function Wep  =
' =================

' Function WEP tells Windows to unload this DLL.  This function
' definition is the same for any DLL.  Certain other run-once
' code can be put here as well, like de-allocating objects.

FUNCTION Wep (BYVAL nParameter AS INTEGER) EXPORT AS WORD

  Wep = 1                              ' Tells WIN that unload
                                       ' was a success.
END FUNCTION


' ===============
'   End Of DLL  =
' ===============