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
:twisted:

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 :twisted:

Why publish a simple API when you can publish a difficult one with just a little extra effort :P

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! :lol: