Oxygen Basic
Programming => Problems & Solutions => Topic started by: Arnold on October 22, 2015, 04:38:59 PM
-
Hi Charles,
when modifying the BCX examples I found that I cannot use some kind of compound expressions when I use unprototyped functions, e.g. with TextOut in MinWin.inc or declared prototyped:
extern lib "GDI32.dll"
...
! TextOut "TextOutA" '5
...
end extern
! TextOut lib "gdi32.dll" alias "TextOutA" (sys hdc, int nXStart, int nYStart, char* lpString, int cbString) as bool
...
'xStart=300-(LEN(T_String)*10/2)
TextOut(hdc,300-(LEN(T_String)*10/2), 15,T_String,LEN(T_String))
xStart=300-(LEN(X_String)*10/2)
TextOut(hdc,xStart,365,X_String,LEN(X_String))
...
Using TextOut unprototyped the first TextOut statement will show nothing or crash, whereas TextOut prototyped works with both statements. This is not a real problem because I can find out the places in question very fast.
Nevertheless I would like to ask if there are some kind of expressions which are allowed with unprototyped functions or is any expression forbidden in these cases?
Another question: is there a better way to find out if an error occurs with compound expressions in an unprototyped function? At the moment I use print statements combined with console.inc. I also use this code snippet which I found in some Oxygen examples:
s=error()
'
if s then
print s
end
end if
but this seems to effect nothing?
Roland
-
With Patrice a regular visitor, maybe he could provide an O2 example of his excellent ZTrace utility.
James
-
Hi Roland,
From running a few tests, I think the problem is using a float division in your unprototyped expressions. This will pass a floating point number instead of an integer.
try using '\' instead of '/'
Currently, The only run-time errors caught by error() are failed identifications of DLL functions.
-
Hello,
Everything seems Okay!
include "asm.inc"
window 640,480,1
hdc = GetBufferDC
Extern lib "GDI32.dll"
! TextOut "TextOutA"
End Extern
'! TextOut Lib "gdi32.dll" Alias "TextOutA" (sys hdc, x, y, string lpString, sys nCount) As Long
! SetTextColor Lib "gdi32.dll" (ByVal hdc As Long, ByVal crColor As Long) As Long
string t_string = "what, who, where"
string x_string = "banana, apples, cherries"
SetTextColor hdc,0xFFFFFF
TextOut hdc ,100,100, t_string, len(t_string)
TextOut hdc ,100,120, x_string, len(x_string)
string wrong = error()
if wrong
mbox "ERROR"
else
mbox "Okay"
end if
waitkey
winExit
[attachment deleted by admin]
-
Peter,
It works OK as long as it passes whole integer arguments:
TextOut sys, sys, sys, ...
or
TextOut sys, sys +|-|*|\ sys, sys +|-|*|\ sys, ...
But it fails with floating point arguments
TextOut sys, sys / sys|float|double, float / sys|float|double, double / sys|float|double, ...
Try
TextOut hdc ,200/2,200/2, t_string, len(t_string)
and it will crash.
Now try
TextOut hdc ,200\2,200\2, t_string, len(t_string)
and it will work.
-
Charles,
My deepest condolences. Been there, seen that. :)
Splitting the incoming flow of arguments into raw 4-byte chunks and pushing them on stack to call an unprototyped 3rd party function is a real PITA. It's a bottleneck in FBSL BASIC's interpreter where all calls to external DLLs are unprototyped.
I suppose it will also work as expected if you use whatever data types there are for the calculation but then explicitly cast the result to an integer or whatever the function expects its arg to be? (that's what the FBSL BASIC user is supposed to do)
At any rate, the programmer calling a 3rd party function will always look up its help file or MSDN to see what args exactly the function expects. He or she can use this occasion to also put appropriate casts in their places by hand rather than rely on the compiler to do that for them. There are too many bugs in header files out there on the net anyway ...
-
Hi Charles,
thank you for this solution. I was not aware of a divison problem using floats/single. But using \ instead of / solved everything. So I know where to look in the future.
And I now realize the usefulness of the error() statement too because I often get the unrecognized dll function error when I make a mistake in the declaration. I only was not able to assign these error messages.
Roland
-
Mike,
include "asm.inc"
window 640,480,1
hdc = GetBufferDC
Extern lib "GDI32.dll"
! TextOut "TextOutA"
End Extern
'! TextOut Lib "gdi32.dll" Alias "TextOutA" (sys hdc, x, y, string lpString, sys nCount) As Long
! SetTextColor Lib "gdi32.dll" (sys hdc, crColor) As Long
string x_string = "WHAT!"
SetTextColor hdc,0x00FFFF
TextOut hdc, int 100/2, int 100/2, x_string, len(x_string)
SetTextColor hdc,0x00FF00
TextOut hdc, int 200\2, int 200\2, x_string, len(x_string)
waitkey
winExit
-
Hi Peter,
you applied a cast.
TextOut hdc, 100/2, 100/2, x_string, len(x_string)
will only work with the prototyped function, whereas
TextOut hdc, 100\2, 100\2, x_string, len(x_string)
will work prototyped and unprototyped.
This is of course no problem at all. I now know that I either can do a cast like you did or I can use a prototyped function.
Roland
-
Exactly, Peter!
It's just a matter of memorizing (and looking up in MSDN, if necessary) that
- if TextOut() wasn't prototyped, it would expect whole integer (sys, int, long, and/or pointer) arguments
- BASIC "\" means integer division and "/" means floating-point division
- integer arithmetics should be used when calc'ing this function's args
- casts should be used (like you did) if arg calc can't be accomplished through integer arithmetics
- as the first measure to be taken if TextOut() was prototyped but still fails, go for its prototype, compare it with MSDN, and make sure the author of the header file translated the prototype to BASIC correctly
-
With function args, Oxygen makes a distinction between cast and convert
If you wnt to pass a float expression or variable, where an int is expected in an unprototyped function:
float f1
...
myfun( hWnd, convert int f1)
-
Thanks, Charles! That must be an important correction. The keyword seems to be missing from the help file, however, along with cast...