Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

DarkBASIC Discussion / DBC DLL return value BUG ? using float array

Author
Message
Latch
18
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 21st Aug 2007 18:54 Edited at: 21st Aug 2007 19:25
I have been pulling out my hair lately trying to figure out why some functions I was using with a DLL seemed to mysteriously break. I had been rewriting an old DBC script for use with the dll. Making a longer story shorter, I thought it had to do with using DOUBLES in a C dll vs using FLOAT values. DOUBLES are twice as large (bitwise) as FLOATS and DBC can only handle FLOATS. So I recompiled the DLL with single precision - no luck!

I found my original DBC script to test this DLL and it worked - both with the old DLL and the newly compiled one? What the heck?

The difference, I found, was that I was using regular float variables in DBC in the original script (a# , value#, etc.) But in the new script, I was using float arrays (a#(2), value#(16), etc.)

From what I can tell, float arrays do not return an expected value from a DLL call that returns a float. Is this a known BUG?

Anyway maybe this post will save some headaches and also, (for myself at least) this solves problems with DLLs I thought couldn't be used with DBC because they simply didn't work. Maybe not so - could just be arrays with DLL calls are quirky.

I've uploaded a DLL that has a few functions that take double and float input and will return double or float output. I'm also including a test script I threw together to show how the array returns the incorrect value and how a regular float variable will return the correct one.

There's an extra function I stuck in this test DLL called MessageOut and it will output a simple message box (up to 255 characters long) if you want to use it for anything.

call dll,<num>,MessageOut,<title$>,<message$>

The DBC version I'm using is 1.13 with the patch from 2002.

[EDIT]
When running the included test script, I've seen only 1 case when the value 123.456 is returned as expected - when sent as a float and returned as a float using a DBC non-array float variable.

Enjoy your day.

Attachments

Login to view attachments
Libervurto
18
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 21st Aug 2007 19:18
Quote: "There should be only 1 case when the value 123.456 is returned as expected - when sent as a float and returned as a float using a DBC non-array float variable."

That's odd , how many did you try!!
Have you made all variables floats, I know that a float from a division with integers wont work, maybe this is the same sort of problem?

Your signature has been erased by a mod because it was rubbish.
empty
22
Years of Service
User Offline
Joined: 26th Aug 2002
Location: 3 boats down from the candy
Posted: 21st Aug 2007 19:27
DBC expects returned float values to be in the EAX register, while compilers return them in the Floating point stack. So your function needs to return an integer to where you copy the content of the float value:



Latch
18
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 21st Aug 2007 19:36 Edited at: 21st Aug 2007 19:44
@empty
The discrepancy occurs between arrays and non arrays in DBC. If I was using a ready made dll, like ODE, or FreeImage, or User32 are you suggesting that I write another dll with a modified function containing the ready made DLL to convert the output to an integer?

@Obese
Quote: "There should be only 1 case when the value 123.456... "

That's specific to the test script.

If you haven't already, download the script and dll and give it a go. The test is between DBC float variables that are declared like
variable#

and array floats such as
variable#(0)

and what the value is after a call to a dll that returns a float or a double. A double shouldn't work it all cases because that is an 8 byte number. A float is usually only 4 bytes and that is what DBC can handle, so it should work. What I've been noticing is that array floats in DBC are not returning the correct values from DLL calls. I was wondering if anyone noticed the same thing.

Enjoy your day.
Libervurto
18
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 21st Aug 2007 19:40 Edited at: 21st Aug 2007 19:52
ohhhhh is THAT what the D is in DWORD etc. "double" Never made the connection lol.
Why can't DB handle 8 bytes?
Memblocks use 8byte numbers all the time?

I'll test it and then I'll probably see what you mean

[edit]
Very strange.
I don't understand why it would go to 2? or 2.8...??
I was expecting to see 1s and 0s
I find the last one most interesting: 1.12348 why would it shift the numbers like that and then where does 8 come from?
my head hurts

Your signature has been erased by a mod because it was rubbish.
Latch
18
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 21st Aug 2007 19:54
Quote: "Memblocks use 8byte numbers all the time?"


Memblocks can store a series of 8 bytes that is true, however, there is no command to have a memblock receive an 8 byte number. A DWORD is a 4 byte number (as is a float) and in DBC's case would be considered a type LONG INT. So the 8 bytes in the memblock would be viewed by any DBC variables as 2 4 byte number or 4 2 byte numbers or 8 1 byte numbers. You could write a function to convert the 8 bytes to a 4 byte float, but it's extra overhead you don't want that will slow the program way down if you write it in BASIC.

What I've done where I had to use a double from a dll is actually make another DLL that contains the function of the original dll and output a float. It's a bit faster than doing it in BASIC - but still a pain.

Enjoy your day.
Libervurto
18
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 21st Aug 2007 19:58 Edited at: 21st Aug 2007 19:59
have you tried "cheating" and splitting it up into two integers?
e.g. "1.2345" becomes "1" and "2345"
or "12345" and what ever the exponent is (is that right? exponent?)

Your signature has been erased by a mod because it was rubbish.
Latch
18
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 21st Aug 2007 20:10
Quote: "have you tried "cheating" and splitting it up into two integers"

Originally when trying to deal with doubles, I was trying to think how to do that. The problem is there are only a certain amount of parameters in a dll function call, so I can't send two parameters when there is only one expected. On the return value, the largest byte size of a number is 4. This basically means that the return value will be the lowest 4 bytes. In a double precision float, those 4 bytes don't contain the sign, or the exponent so it is a completely different number than you'd expect.

Quote: "I don't understand why it would go to 2? or 2.8...??"

That's part of the reason the return values are so weird - for doubles it's not going to be a reflection of what you'd expect in a float if it's only the lower 4 bytes of the 8.

As far as DBC's float array differing from the regular float variable, it probably has to do with what empty was talking about. For me, I just won't use arrays with dll calls. I can read them into regular variables and then set the value of the array from the regular variable.

Enjoy your day.
Libervurto
18
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 21st Aug 2007 21:08
have you tried making two calls and transferring the data serially.
Ah yeah I was having problems with editing a mesh with memblocks, that's probably because they use 8byte data too.

Your signature has been erased by a mod because it was rubbish.
empty
22
Years of Service
User Offline
Joined: 26th Aug 2002
Location: 3 boats down from the candy
Posted: 21st Aug 2007 21:29 Edited at: 21st Aug 2007 21:31
Quote: "The discrepancy occurs between arrays and non arrays in DBC."

Yes, you are right. Apparently you can't return floats to a float array. I haven't notice that before. Good spot!

Quote: "If I was using a ready made dll, like ODE, or FreeImage, or User32 are you suggesting that I write another dll with a modified function containing the ready made DLL to convert the output to an integer?"

Absolutely!
The fact that your test appears to work is because your routines temporarily store the value in EAX do to other stuff with it (in this case, it stores it in a local variable).



However, it may well be that the EAX register is overwritten by other values before the function returns.
To test this behaviour, try returning a float constant. In this case the compiler shouldn't touch the EAX register at all.

Latch
18
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 21st Aug 2007 23:21
@empty
What disassembler did you use?

Quote: "The fact that your test appears to work is because your routines temporarily store the value in EAX do to other stuff with it (in this case, it stores it in a local variable). "

Are you saying it's a gamble as to whether or not a dll will return the correct value in a float from a DBC dll call? I hope not, 'cause that would really stink! I started this thread because I noticed the values never returned correctly in a float array in DBC, but now maybe there could be other situations when a float just doesn't come back right... I'll test out the constant a little later. I'm not ready to be depressed. But thank you for your explanation!

@Obese
Quote: "Ah yeah I was having problems with editing a mesh with memblocks"


Actually all the values in a memblock converted from a mesh should be ok. You just have to make sure the position you reference in the memblock is accurate and for the correct data type (DWORD, FLOAT, BYTE etc.) I wrote a fairly complete vertex library that reads and sets the values in a mesh memblock (including normals, vertices, uv data, faces...) I'll look around for it. I remember in the Code Base there is another memblock vertex library, though I don't remember what it is called. Probably Vertex Library! So, take a look in the code base...

Enjoy your day.
empty
22
Years of Service
User Offline
Joined: 26th Aug 2002
Location: 3 boats down from the candy
Posted: 21st Aug 2007 23:40 Edited at: 21st Aug 2007 23:42
Quote: "What disassembler did you use?"

PE-Browse

Quote: "Are you saying it's a gamble as to whether or not a dll will return the correct value in a float from a DBC dll call?"

Only if you don't copy the result to the EAX register. Like I said, DB (and DBP as well) expects float results to be returned in that register rather than on the floating point stack where compilers would put it normally.


Edit: I've attached a test to demonstrate that.

Delphi source of the DLL


Attachments

Login to view attachments
Latch
18
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 22nd Aug 2007 00:22 Edited at: 22nd Aug 2007 00:23
@Obese
Vertex Library from code base
It's labeled as being DBPro, but after eyeballing the functions, I think it should be applicable to DBC. Give it a shot, you'll find out for sure.

http://www.thegamecreators.com/?m=codebase_view&i=0063914c336f09ffb250afed7791e0d3

@empty
Your example nearly blew up my machine! That happened alot when messing with float arrays and dlls.

So I'm at the mercy of the DLL if I want to use one off the shelf. But at least I should be able to deal with the situation now by writing a custom function. Thanks empty! Any idea what is going on with the Float arrays though?

Enjoy your day.
Libervurto
18
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 22nd Aug 2007 02:23
Thanks Latch, I made an array to store the vertice data but this is much better

Your signature has been erased by a mod because it was rubbish.

Login to post a reply

Server time is: 2025-05-27 22:28:22
Your offset time is: 2025-05-27 22:28:22