Page 1 of 1
How to convert this from C to PB?
Posted: Wed Sep 12, 2007 6:33 am
by Mistrel
I'm trying to convert this bit of C into PB to return a floating point number to DarkBasic from my dll but I can't seem to make it work. I don't understand what's actually happening in the C function. Would someone explain this to me?
Code: Select all
MYCOMMAND DWORD ReturnAFloat(void)
{
float fValue = 42.05f;
return *(DWORD*)&fValue;
}
Posted: Wed Sep 12, 2007 6:52 am
by citystate
I think it's the equivalent of
Code: Select all
Procedure.f ReturnAFloat()
fValue.f = 42.05
ProcedureReturn fValue
EndProcedure
Posted: Wed Sep 12, 2007 6:58 am
by Maxus
Maybe this code rule.
Code: Select all
Structure AFloat
StructureUnion
F.F
L.L
EndStructureUnion
EndStructure
Procedure.l ReturnAFloat()
fValue.AFloat\F = 42.05
ProcedureReturn fValue\L
EndProcedure
Posted: Wed Sep 12, 2007 7:10 am
by pdwyer
my take on it
Code: Select all
Procedure.l ReturnAFloat()
fValue.f = 42.05
ProcedureReturn @fValue
EndProcedure
Maybe you'd need to declare float as static so that it didn't fall out of scope when the proc exited
Posted: Wed Sep 12, 2007 7:27 am
by Mistrel
Maxus it worked! Thank you! But how?
Thanks to everyone else who posted some code. All of those were variations I tried too.
Posted: Wed Sep 12, 2007 8:01 am
by Maxus
Mistrel wrote:Maxus it worked! Thank you! But how?
Thanks to everyone else who posted some code. All of those were variations I tried too.
What is how?
The whole secret lies in the structure that we declare above.
Code: Select all
StructureUnion
F.F
L.F
EndStructureUnion
F.F and
L.L invoked in this case at the same station memory.
When you write
F.F = 42.05 it can be the opposite numbers through
L.L
Posted: Thu Sep 13, 2007 10:38 am
by pdwyer
I see, kind of like type spoofing so that you can return 4 bytes as a dword but actually there's a 4 byte float in there.
Wonder what the point of doing that is?
Posted: Thu Sep 13, 2007 10:53 am
by Kaeru Gaman
> Wonder what the point of doing that is?
additionally, there is alwys the same Value used...
instead of calling this procedure, I could just put a 0x42283333 into the C-code..
is the author trying to hide some key by this action?
but the literal float will appear as a 42283333 in a hex-viewer, too...
Posted: Thu Sep 13, 2007 11:11 am
by pdwyer
Okay, searching around on the net it seems to be a darkbasic workaround where by their DLL can't return floats so they need to sort of encpsulate it to get around a limitation of the language
Posted: Thu Sep 13, 2007 11:22 am
by Fluid Byte
... a darkbasic workaround where by their DLL can't return floats so they need to sort of encpsulate it to get around a limitation of the language

Posted: Fri Sep 14, 2007 7:29 am
by Mistrel
pdwyer wrote:I see, kind of like type spoofing so that you can return 4 bytes as a dword but actually there's a 4 byte float in there.
Wonder what the point of doing that is?
This really turns my head around. The code returns a float as a long without type-casting. That's kind of neat.
Posted: Fri Sep 14, 2007 10:53 am
by pdwyer
hmmmm,
Well, my name is four letters so I could set a longs bytes to asc(P) asc(a) asc(u) asc(l) and return it as a long.
Or I could return it as a string since that's what it is...
But noooo, I will not make it that easy for them
Why publish a simple API when you can publish a difficult one with just a little extra effort

Posted: Fri Sep 14, 2007 4:07 pm
by Kaeru Gaman
Code: Select all
Structure Essense
StructureUnion
Name.s{4}
Esse.f
EndStructureUnion
EndStructure
Define Test.Essense
Test\Name = "Paul"
Debug Test\Esse
Posted: Fri Sep 14, 2007 6:46 pm
by GedB
The following includes an alternative approach which uses PeekL instead of a StructureUnion. It does the cast in a single line, just like the C code.
Code: Select all
;-Testing Methods
TestsRun.l = 0
TestsPassed.l = 0
TestsFailed. l = 0
Procedure AssertEqualsL(expected.l, actual.l)
Shared TestsRun
Shared TestsPassed
Shared TestsFailed
TestsRun+1
If actual = expected
TestsPassed+1
Else
TestsFailed+1
Debug "Assertion Failed: expected " + Str(expected) + " but received " + Str(actual)
EndIf
EndProcedure
Procedure TestReport()
Shared TestsRun
Shared TestsPassed
Shared TestsFailed
Debug "----------------------------------------------------------------------------------------"
Debug "Test Report. Run ("+Str(TestsRun)+") Passed ("+Str(TestsPassed)+") Failed ("+Str(TestsFailed)+")"
Debug "----------------------------------------------------------------------------------------"
EndProcedure
;-Solution I using Structured Union
Structure AFloat
StructureUnion
F.F
L.L
EndStructureUnion
EndStructure
Procedure.l ReturnAFloatI(value.f)
fValue.AFloat\F = value
ProcedureReturn fValue\L
EndProcedure
;-Solution II using PeekL
Procedure.l ReturnAFloatII(value.f)
ProcedureReturn PeekL(@value)
EndProcedure
;-Test Soluction I
AssertEqualsL( ReturnAFloatI(42.03) , 1109925560)
AssertEqualsL( ReturnAFloatI(-89.3333334) , -1028478293)
AssertEqualsL( ReturnAFloatI(82489.45) , 1201740986)
;-Test Soluction II
AssertEqualsL( ReturnAFloatII(42.03) , 1109925560)
AssertEqualsL( ReturnAFloatII(-89.3333334) , -1028478293)
AssertEqualsL( ReturnAFloatII(82489.45) , 1201740986)
TestReport()
Posted: Sat Sep 15, 2007 2:59 am
by pdwyer
Kaeru Gaman wrote:Code: Select all
Structure Essense
StructureUnion
Name.s{4}
Esse.f
EndStructureUnion
EndStructure
Define Test.Essense
Test\Name = "Paul"
Debug Test\Esse
Too much free time!
