Thanks Bernd (infratec)
Just to put into perspective my understanding of the way DLL calls can be made using Prototypes, my learning is as follows:
DLL File:
1. In the "ProcedureDLL AttachProcess(Instance.l).....EndProcedure" area we need to define the variables those will be "passed on" to the calling program. In my version we have "Global DLLString.s = "", Hr12.i, Min.i, Sec.d, SecD.d"
2. The ProcedureDLL must be defined as .s or.i or.d etc to signify the type of variable that needs to be passed from the DLL.
3. In case we do not define as 2 above, we can pass from a single ProcedureDLL multiple types of variable types.
4. Bytes, integers, words, longs are handled internally by the "CallFunction" command and we need to only define the variables in the ProcedureReturn command.
5. Doubles, Floats and Strings can be passed through pointers to the variable ONLY provided they are mentioned as in 1 above.
Test file:
1. The Library file (*.dll) needs to be opened BEFORE any function in the DLL is used and as good practice MUST be CLOSED before program ends.
2. A prototype definition needs to be done as an "integer" variable as the addresses to the function in the DLL shall be passed to it.
3. The name of this Prototype can be anything, BUT need to ensure that they contain the required arguments and their variable types are as per the Function definition in the DLL. In the case below I have given the name "AnyPrototypeName(D.d, i.i)"
4. Now a name to the Calling Function as a variable type of the above Prototype needs to be given which in this case is "AnyCallingName".
5. This calling name of type "prototype" as defined now takes the value of the DLL Function through the "GetFunction" command.
6. For bytes, integers, words, longs variable type, the above named "Calling function" needs to be called with the Function arguments in brackets.
7. For doubles, floats and strings, see point 5 under "DLL File" above, we need to "Peek" at the above calling function (which carries the function address) for the particular variable type that is required, hence PeekD for double and PeekS for strings.
Please see the test files as below for understanding.
DLL FILE:
Code: Select all
ProcedureDLL AttachProcess(Instance.l)
Global DLLString.s = "", Hr12.i, Min.i, Sec.d, SecD.d
EndProcedure
ProcedureDLL ConvertDecimaltoHMS12(DecimalValue.d, index.i)
Hr.d = Int(DecimalValue)
If Hr > 12
Hr12 = Hr - 12
AmPm.s = "PM"
Else
Hr12 = Hr
AmPm = "AM"
EndIf
MinD.d = (DecimalValue - Hr) * 60
Min = Int(MinD)
SecD.d = (MinD - Min) * 60
Sec = Int(SecD)
DLLString = Str(Hr12) + ":" + Str(Min) + ":" + StrD(SecD,2) + " " + AmPm
Select index
Case 1
ProcedureReturn Hr12 ; notice no @ sign as variable is an integer
Case 2
ProcedureReturn Min ; notice no @ sign as variable is an integer
Case 3
ProcedureReturn @SecD ; notice @ sign as variable is a double
Case 4
ProcedureReturn @DLLString ; notice @ sign as variable is a string
EndSelect
EndProcedure
And the Test Code to test the above DLL File:
Code: Select all
If OpenLibrary(0, "mydll.dll")
Prototype.i AnyPrototypeName(D.d, i.i)
jj.d = 17.5236
AnyCallingName.AnyPrototypeName = GetFunction(0, "ConvertDecimaltoHMS12")
Debug AnyCallingName(jj, 1)
Debug AnyCallingName(jj, 2)
Debug PeekD(AnyCallingName(jj, 3))
Debug PeekS(AnyCallingName(jj, 4))
Debug " "
Else
Debug "Error Opening Library"
EndIf
CloseLibrary(0)
I hope my understanding is correct and if not please let me know where my concept differs.
Thanks Bernd once again for explaining the concept as above. Hope my note helps newbies like me to understand DLL procedure functionality.
Regards