Science makes it known,
Engineering makes it work,
Art makes it beautiful.
|
|
Simple Pascal Windows program calling D procedure and FORTRAN Function
proot is a very simple Pascal Windows program demonstrating
calling D and FORTRAN subprograms (and it does
something
useful, unlike Hello World) - calculates
N
√ X
.
proot uses Win32 API calls
and three .dll's (described below).
Files:
-
proot.pas
- Windows main program, developed using
Free Pascal.
For those just learning Win32 API programming,
proot.pas is commented as to what each section is doing.
-
hwndio.pas
- collection of Free Pascal general purpose functions for Windows Edit
Boxes I/O, field tabbing. Source
code is commented as to purpose. Compile with batch file
fpcdll.bat
hwndio.dll - hwndio.pas dynamic link library
hwndio.lib - not used in this application;
hwndio.pas import library, built using Digital Mars
implib utility (file bup.zip);
used by a more advanced version of
Simulated Annealing Demonstration;
D requires import libraries.
-
heditio.d
- as described in
D module hedtio,
collection of D functions for Windows Edit Boxes I/O, Keyboard
Interface
for a Standard Scroll Bar, right click short cut popup menu
for basic clipboard operations; proot calls procedure
hEditInitMsg(...) to set the edit control
child window's font using its D mangled name (identified using
Dependency Walker,
see graphic below)
hedtio.di
- not used in this application;
hedtio.d d interface file, can be used by DMD when compiling D main
program
(instead of using hedtio.d for the module definition)
hedtio.dll - hedtio.d dynamic link library; built by
chedtio.bat
using
Digital Mars D compiler.
hedtio.lib - not used in this application;
hedtio.d import library; built by chedtio.bat during the compilation
process
-
sttstcs.for
function
NROOT (...)
- function subprogram in sttstcs.for to compute
N
√ X
;
to prevent a possible intellectual
property violation, limited sttstcs.for source code available for
download, since the original FORTRAN source code is
published; the unmodified
Numerical Recipes Statistical Analysis FORTRAN source code is
available at
Older Numerical Recipes book editions.
sttstcs.dll - sttstcs.for dynamic link library; built using
Silverfrost FTN95 Plato IDE
sttstcs.lib
- not used in this application;
sttstcs.for import library;
this can be either MicroSoft linker compatible
OR Digital Mars D compatible.
The D compiler "mangles" function/procedure names when compiling
source code - the mangled name is what is stored
in the import library
(hedtio.lib) and dynamic link library (hedtio.dll); this is the
procedure name (mangled) to use to call from
Pascal, not the procedure name (unmangled) in the d
interface file (hedtio.di).1 Will need to use
Dependency Walker
(or a
similar tool) to identify the mangled name in the .dll
(hedtio.dll).
Open either a D executable calling hEditInitMsg (...) or
hedtio.dll itself,
look in Export Function List View (middle right)
for a function
name containing hEditInitMsg (highlighted below) - this is the
mangled name to use for the call - in this case it
is D6hedtio12hEditInitMsgFNbPvZv. Some
types of modifications to the D function will cause a change in the
function's
mangled name, making it necessary to modify and recompile the
Pascal .dll/program.
External Procedures:
GET_SMALLINT (...) checks that the contents of the child window
(or edit control)
is a valid smallint, converts it to a smallint, and
returns the value in i.
GET_DOUBLE (...) performs a similar operation for doubles
GET_SMALLINT (...) is also used by a D Windows program, and is
declared with the following:
extern (Pascal)
{
short GET_SMALLINT (ref short, HWND) nothrow;
}
in the D program.
When compiling a D program,
extern (Pascal) automatically makes the procedure name
upper case letters, D is case sensitive, therefore the names of any
procedures declared extern Pascal must be upper case.
Subprograms
written in other programming languages that are case insensitive and are
to be called by D, as in the case of GET_SMALLINT (...),
must have all upper case function/procedure/subroutine
names.2
Functionally, have found extern (Pascal) is
D's closest approximation to stdcall.3
PutSmallint(...) converts a smallint to char, then
outputs it in a child window edit control
PutDouble2(...) converts and formats a double to char
using FloatToStrF (...),
then outputs it in a child window edit control
hWndTabMsg(...) allows the user to tab from edit control to
edit control
|
The resulting external procedures definitions:
D6hedtio12hEditInitMsgFNbPvZv (...) is the D mangled name for
procedure hEditInitMsg in module
hedtio
and is called using cdecl. (in a few cases
Pascal calling D may produce run-time or other errors; this
has been limited to
procedures passing record structures - adjusting {$packrecords }
may solve problem; a second problem area can be
passing by value
an element from a HWnd array - solution is to define a single
HWnd variable, move HWnd array element to that variable, and pass that
variable; another tricky area is character
arrays; as a general rule, have found D calling non-D
functions/procedures/subroutines to be more robust than
the other way around; it is possible I may have missed something
in the D documentation.)
NROOT (...) is in the FORTRAN sttstcs.dll and uses
stdcall. FORTRAN is case insensitive, so use all upper case
letters for names. By default, FORTRAN expects all arguments to be
passed by reference.
|
Compiling/Linking:
-
Create, compile, and link sttstcs.for.
-
Compile and link hedtio.d into hedtio.dll:
Open D2 32-bit Command Prompt
chedtio
-
Compile and link hwndio.pas into hwndio.dll:
In the same D2 32-bit Command Prompt
fpcdll hwndio
-
Compile and link proot.pas into proot.exe:
Run the Free Pascal IDE, open and compile proot.pas
1. Have successfully experimented in another Pascal
Windows application calling the D function at right (listing shown is
an early version; download
hedtio.di
and
hedtio.d
for latest version; function contains additional comments and error
processing). Both cPopUpMenu (...) and
hEditPopUpMenu (...) are functions in
module hedtio.
Declared cPopUpMenu (...) extern (C) to avoid
D6hedtio12hEditInitMsgFNbPvZv (...) issues mentioned above.
In this instance, the D compiler did not mangle function name
cPopUpMenu.
In the Pascal Windows application, if the user
right-clicks in an element of an
edit control array (element passed as hEdit),
cPopUpMenu (...) is called.
cPopUpMenu (...) performs some initialization (including
calling _control87(...)), calls
hEditPopUpMenu (...), returning the result to
the Pascal Windows application. This
successfully
displays the D custom pop up menu.
It is necessary to call _control87(...) to prevent an
EInvalidOP crash when
hEditPopUpMenu (...) is
|
|
called (probably due to the try {...} catch {...}
processing in hEditPopUpMenu (...)).
_control87(...) is defined in the D
runtime, and declared in
hedtio.d with extern (C) {...}. _MCW_EM
is a constant defined in hedtio.di and hedtio.d.
popup.inc
is a Pascal include file of constants returned by
cPopUpMenu (...). Initial testing
indicates this is a more reliable
method than that
used for calling hEditInitMsg (...).
2. See
Mixing Languages
for additional insight on DMD compilers (excluding D) linkage with C,
FORTRAN, and Pascal
functions.
3. See
PASCAL-style and STDCALL calling conventions
for additional information.
|