Invoking DLL functions (Original Enhancement )
An Internal or external function or subprogram except DEF can be defined using a DLL.
In that case, the following style of ASSIGN statement is written between the FUNCTION line and the END FUNCTION line or the SUB line and END SUB line.
ASSIGN DLL-file-name , function-name
where DLL-file-name and function-name are string constants.
Example
FUNCTION GetVersion
ASSIGN "kernel32.dll","GetVersion"
END FUNCTION
DLL-file-name indicates the DLL that contains the function we want to use. Function-name indicates the function in the DLL. Function-name is case sensitive.
Numeric arguments are evaluated as 32bit or 64bit integers cutting off the upper digits to be passed. The arguments are always passed by value even if the procedure is a SUB program.
A string argument is passed as a pointer that points the first character of it. But it is a null string, the null pointer shall be passed, which is not a pointer to a null string.
When the DLL does not deal the nul pointer as a null string, use chr$(0).
When a function is defined as a string function, it must be a function that returns a pointer that points a null terminated ASCII string.
Example 1
DECLARE EXTERNAL FUNCTION MesBox
LET n=MesBox(0,"Hello","BASIC",3)
PRINT n
END
EXTERNAL FUNCTION MesBox(owner,text$,caption$,flag)
ASSIGN "user32.dll","MessageBoxA"
END FUNCTION
We use a string variable for a DLL function's argument which is an address of a variable. We prepare sufficient size of memory that the DLL function requires for the argument by making the length of the string as long as required, using a REPEAT$-function or so. We cannot make that string variable by substituting another string variable for it. And that string variable cannot have been substituted for any other string variable.
We can get the received value using substring operation. A string variable can be used a byte buffer when OPTION CHARACTER BYTE is declared in the program unit where the substring operation shall be done.
Example 2
DECLARE EXTERNAL FUNCTION CurrDir$
PRINT CurrDir$
END
EXTERNAL FUNCTION CurrDir$
OPTION CHARACTER BYTE
FUNCTION GetCurrentDirectory(n,s$)
ASSIGN "kernel32.dll","GetCurrentDirectoryA"
END FUNCTION
LET s$=Repeat$(" ", 200)
LET n=GetCurrentDirectory(200,s$)
LET CurrDir$=s$(1:n)
END FUNCTION
In Windows 32, to invoke a DLL compiled with CDECL calling convention, write following style ASSIGN statements.
ASSIGN DLL-file-name , function-name ,CDECL
On Linux(32bit), we assume CDECL by default. Replace CDECL with STDCALL on invoking a DLL compiled with StdCall cnvention.
<Supplement.> An ASSIGN statement raises an exception of extype -9900 when it receives an OS exception, while exceptions that might be occur in a DLL ought to be handled in the DLL.
<Notice.> Any identical DLL routine can not be available in anther ASSIGN statement. They are Recommended to be written in external procedures.
<Notice.> In some OSs, invoking a DLL that deals with GUI may cause a a fault.
<Notice.> The DLL is loaded on compiling. When another DLL linking it occurs a load error, the load error shall be shown with the name of specified in the program.
<Notice.> An error on the number of arguments shall not be checked when the program is compiled and when the program runs. Thus a mistake on the number of parameters causes a miserable result.
<Note.> A function that converts a signed 32 bit integer to the hexadecimal representation of its unsigned evaluation.
BSTR$(MOD(n, 4294967296),16)
<Reference.> ORD-function and CHR$-function, Substring
Supplied functions (Windows only)
ANSI$(string-expression)
Convert to the Windows ANSI string.
Example.
10 DECLARE EXTERNAL FUNCTION MesBox$
20 CALL MesBox(0,ANSI$("漢字"),ANSI$("BASIC"),3)
30 END
100 EXTERNAL SUB MesBox(owner,text$,caption$,flag)
110 ASSIGN "user32.dll","MessageBoxA", GUI
120 END SUB
WIDE$(string-expression)
Convert to the Windows Wide character string(UTF-16).
Example.
10 DECLARE EXTERNAL FUNCTION MesBox$
20 CALL MesBox(0,WIDE$("髙木"),WIDE$("BASIC"),3)
30 END
100 EXTERNAL SUB MesBox(owner,text$,caption$,flag)
110 ASSIGN "user32.dll","MessageBoxW", GUI
120 END SUB
ImportANSI$(string-expression)
Convert a Windows ANSI-string to the internal string(UTF-8).
ImportWIDE$(string expression)
Convert a Windows Wide character string to the internal string(UTF-8)
WINHANDLE(s$)
The handle of the system window (or control) to be passed to Win32 API.
s$ is one of the following.
"MAIN", "TEXT", "GRAPHICS", "INPUT", "CHARACTER INPUT","TRACE", "LOCATE", "LOCATECHOICE"
Differences in case are ignored.
IF another one is designated, the function result shall be zero, generating no exception.
Example 1.
100 DECLARE EXTERNAL SUB MoveTextWindow, ResizeTextWindow
110 FOR i=1 TO 5
120 PRINT "Hello"
130 CALL MoveTextWindow(i*100,i*60)
140 CALL ResizeTextWindow(320,160+i*20)
150 WAIT DELAY 1
160 NEXT i
170 END
180 EXTERNAL SUB MoveTextWindow(x,y)
190 SUB SetWindowPos(hwnd,HwndInsAfter,x,y,cx,cy,nFlags)
200 ASSIGN "user32.dll","SetWindowPos"
210 END SUB
220 CALL SetWindowPos(WinHandle("TEXT"),0,x,y,0,0,1)
230 END SUB
240 EXTERNAL SUB ResizeTextWindow(x,y)
250 SUB SetWindowPos(hwnd,HwndInsAfter,x,y,cx,cy,nFlags)
260 ASSIGN "user32.dll","SetWindowPos"
270 END SUB
280 CALL SetWindowPos(WinHandle("TEXT"),0,0,0,x,y,2)
290 END SUB