Page 1 of 2
[PB4.20b2] Debug PeekF(@v1+OffsetOf(...)) works not always
Posted: Thu Mar 27, 2008 8:38 am
by IceSoft
This source code works correct:
Code: Select all
Structure cpVect
x.f
y.f
EndStructure
If OpenLibrary(1,"chipmunk-4.0.2.dll")
func = GetFunction(1,"cpvforangle")
v1=CallFunctionFast(func,#PI/4.0)
x1.f = PeekF(@v1+OffsetOf(cpVect\x))
y1.f = PeekF(@v1+OffsetOf(cpVect\y))
Debug x1
Debug y1
Debug PeekF(@v1+OffsetOf(cpVect\x))
Debug PeekF(@v1+OffsetOf(cpVect\y))
EndIf
Debug output:
0.70710676908493
0.70710676908493
0.70710676908493
0.70710676908493
This code works not correct (same as above with a small change in the command order)
Code: Select all
Structure cpVect
x.f
y.f
EndStructure
If OpenLibrary(1,"chipmunk-4.0.2.dll")
func = GetFunction(1,"cpvforangle")
v1=CallFunctionFast(func,#PI/4.0)
Debug PeekF(@v1+OffsetOf(cpVect\x))
Debug PeekF(@v1+OffsetOf(cpVect\y))
x1.f = PeekF(@v1+OffsetOf(cpVect\x))
y1.f = PeekF(@v1+OffsetOf(cpVect\y))
Debug x1
Debug y1
EndIf
Debug output:
0.70710676908493
0.0
0.70710676908493
0.70710676908493
Posted: Thu Mar 27, 2008 9:20 am
by Hroudtwolf
Hi,
If "CallFunctionFast(func,#PI/4.0) " retrieves an address, you should use a pointer.
"@v1+OffsetOf(cpVect\x)" makes an offset to the adress of the long variable and not of the retrieved address.
Try to use.
Code: Select all
Structure cpVect
x.f
y.f
EndStructure
If OpenLibrary(1,"chipmunk-4.0.2.dll")
func = GetFunction(1,"cpvforangle")
*v1=CallFunctionFast(func,#PI/4.0)
x1.f = PeekF(*v1+OffsetOf(cpVect\x))
y1.f = PeekF(*v1+OffsetOf(cpVect\y))
Debug x1
Debug y1
Debug PeekF(*v1+OffsetOf(cpVect\x))
Debug PeekF(*v1+OffsetOf(cpVect\y))
EndIf
or
Code: Select all
Structure cpVect
x.f
y.f
EndStructure
If OpenLibrary(1,"chipmunk-4.0.2.dll")
func = GetFunction(1,"cpvforangle")
*v1.cpVect =CallFunctionFast(func,#PI/4.0)
debug *v1\x
debug *v1\y
EndIf
Posted: Thu Mar 27, 2008 10:01 am
by IceSoft
@Wolf,
On both code examples I getting an IMA.
(Have you really test your source?)
Posted: Thu Mar 27, 2008 10:05 am
by Hroudtwolf
I doesn't have your DLL.
And I really don't know what the call is retrieving.
Hroudtwolf wrote:
If "CallFunctionFast(func,#PI/4.0) " retrieves an address
You self should know exactlier what the call is retrieving.
Posted: Thu Mar 27, 2008 10:23 am
by iNX
The original source posted can't work, in my opinion, because @v1+OffsetOf(cpVect\x) ends up in memory allocated by PureBasic and we really don't know what we're going to read.
The Hroudtwolf version seems correct, and maybe the problem lies in the return value of the library function, or in the way it's being called.
I would check those things.
Posted: Thu Mar 27, 2008 10:28 am
by Fred
Are you sure the memory area returned by your DLL is static (persistent even after the function call) and not locally allocated on the stack ? That would explain such behaviour.
Posted: Thu Mar 27, 2008 10:28 am
by IceSoft
However,
My bug message is more written because of the different debug output.
Posted: Thu Mar 27, 2008 10:36 am
by iNX
Since you're reading memory used internally by Purebasic, changing the valour of variables modifies this memory and you're obtaining different results.
Posted: Thu Mar 27, 2008 10:43 am
by IceSoft
Fred wrote:Are you sure the memory area returned by your DLL is static (persistent even after the function call) and not locally allocated on the stack ? That would explain such behaviour.
@Fred,
Seems to be not static.
=>
@Fred have you some hints for me for a working PB source?
Here is also the descriptions of the function:
Code: Select all
cpVect cpvforangle(const cpFloat a)
Returns the unit length vector for the given angle (in radians).
And here are the source parts:
Code: Select all
cpVect
cpvforangle(const cpFloat a)
{
return cpv(cos(a), sin(a));
}
Code: Select all
static inline cpVect
cpv(const cpFloat x, const cpFloat y)
{
cpVect v = {x, y};
return v;
}
Posted: Thu Mar 27, 2008 10:51 am
by IceSoft
iNX wrote:Since you're reading memory used internally by Purebasic, changing the valour of variables modifies this memory and you're obtaining different results.
PB bug?
Posted: Thu Mar 27, 2008 10:54 am
by iNX
IceSoft wrote:iNX wrote:Since you're reading memory used internally by Purebasic, changing the valour of variables modifies this memory and you're obtaining different results.
PB bug?
No, no.. it's normal behaviour. We are not supposed to read memory in this way.
Posted: Thu Mar 27, 2008 10:58 am
by IceSoft
iNX wrote:No, no.. it's normal behaviour. We are not supposed to read memory in this way.
Ok. Please show my the correct way (PB source) to read it.
Posted: Thu Mar 27, 2008 11:28 am
by iNX
Unfortunately i can't be of much help other than explaining why your code was acting that way. In fact now your problem narrows down to handle a library call that returns a structure, instead of a pointer to a structure.
I don't know how to handle such case in purebasic, i think it's not natively supported. Hope someone could be of more help.
Posted: Thu Mar 27, 2008 11:47 am
by Fred
IceSoft wrote:Fred wrote:Are you sure the memory area returned by your DLL is static (persistent even after the function call) and not locally allocated on the stack ? That would explain such behaviour.
@Fred,
Seems to be not static.
=>
@Fred have you some hints for me for a working PB source?
Here is also the descriptions of the function:
Code: Select all
cpVect cpvforangle(const cpFloat a)
Returns the unit length vector for the given angle (in radians).
And here are the source parts:
Code: Select all
cpVect
cpvforangle(const cpFloat a)
{
return cpv(cos(a), sin(a));
}
Code: Select all
static inline cpVect
cpv(const cpFloat x, const cpFloat y)
{
cpVect v = {x, y};
return v;
}
If it's not static, then the result are stored on the stack. Assigning a structure to a structured PB variable is not supported natively by PureBasic, so you will have to copy it as soon as possible, without destroying the stack in between (which can be difficult). It's not a PB bug.
Posted: Thu Mar 27, 2008 12:10 pm
by Fred
As a suggestion, i would use a pointer directly:
Code: Select all
*v1.cpVect = CallFunction...
x1.f = *v1\x
y1.f = *v1\y
This will probably work everytime as no call are done in between.