[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: lua_pushinteger - value stored in the Lua stack differs from passed to function
- From: Rena <hyperhacker@...>
- Date: Fri, 8 May 2015 11:35:10 -0400
On Thu, May 7, 2015 at 10:13 PM, "书呆彭, Peng Yi" <nerditation@outlook.com> wrote:
> 在 2015/5/8 1:20, Paulo Roberto 写道:
>>
>> I just tried to use *string.format* instead of using the operator *..* and
>> it worked fine.
>> The new Lua code:
>>
>> /if (lua_type == 'transaction') then
>> shiftno = tran.getshiftno()
>> dev.log(string.format('ShiftNumber: %d' , shiftno))
>> tran.print(string.format('ShiftNumber: %d' , shiftno))
>> end/
>>
>> The question is: why the operator *..* does not work on this platform and
>> works on Linux and others platforms I have here.
>> The Lua source code used to build the libraries were the same.
>>
>> Thank you again.
>>
>> Regards.
>>
>> On Thu, May 7, 2015 at 11:50 AM, Paulo Roberto <betobrandao@gmail.com
>> <mailto:betobrandao@gmail.com>> wrote:
>>
>> Hello,
>>
>> I'm getting a strange behavior using the functions /lua_pushinteger/
>> and /lua_pushunsigned/.
>>
>> When calling these functions, the value stored in the Lua stack /L/ is
>> not the value passed to the function (an integer), actually It is a small
>> float number.
>> It seems there is some sort of error converting values as all Lua
>> numbers are stored as /double/ numbers.
>>
>> For example, passing the value /37/, the Lua layer receives
>> /5.3265215697135e-315/
>>
>> I'm using *lua 5.2*, *gcc 4.3.4*, building for ARM processors, 32 bits
>> words.
>> I'm passing the compile flag/LUA_COMPAT_ALL/ and /LUA_ANSI/
>>
>>
>> The code I'm using is something like this:
>>
>>
>> /int GetShiftNumber(lua_State *L)
>> {
>> lua_pushinteger(L, gsConfig.ShiftNumber);
>> #ifdef RUNLOG2
>> sprintf(NurLogBuf, "GetShiftNumber: shiftno = %lu",
>> gsConfig.ShiftNumber);
>> Log2(NurLogBuf);
>> #endif
>> return(1);
>> }
>>
>> /
>> The/Log2/ just logs the values on the RS232 port.
>>
>> The Lua code that invokes the C code above is:
>>
>> /if (lua_type == 'transaction') then
>> shiftno = tran.getshiftno()
>> dev.log('ShiftNumber: ' .. shiftno)
>> tran.print('ShiftNumber: ' .. shiftno)
>> end
>>
>> /
>> /
>> /
>> The/tran.getshiftno/ is the corresponding Lua function for the above
>> /GetShiftNumber/.
>> The /dev.log/ function just invokes the C Log2 function.
>>
>>
>> On the C layer, the variables are correct displayed:
>>
>> /GetShiftNumber: shiftno = 37/
>>
>> On the Lua layer, the /shiftno/ is incorrect, /dev.log/ displays:
>>
>> /ShiftNumber 5.3265215697135e-315/
>>
>> The /gsConfig/ is a global structure and the
>> field/gsConfig.ShiftNumber/ is an /unsigned long/.
>> I also tried to use the lua_pushunsigned and got the same result.
>> Then I created a local /int/ variable, did and explicit cast and
>> passed the local variable to /lua_pushinteger/ but nothing changed.
>>
>> Passing values from Lua layer to C layer works fine.
>> The same code, works fine in other platforms.
>>
>> Could you help me to find a solution for this issue?
>>
>> Thank you in advance.
>>
>> Paulo Roberto Brandão.
>>
>>
> I guess it's a flaw of the CRT on your device, or you just misconfigured
> Lua.
>
> I remember `tostring` use the `%g` format to convert a number to string
> under
> the default configuration. either you libc doesn't deal with `%g` correctly,
> or
> you have a configuration using other format specifier.
>
> check your `luaconf.h`; I believe the config definition is called
> `number2str`.
>
>
> --
> the nerdy Peng / 书呆彭 / Sent from Thunderbird
>
>
>
A quick test shows that 37 = 0x25, and 5.3265215697135e-315 is close
to a double value that begins with 0x25 (probably it's been rounded),
so I suspect some code is assuming it's been given a pointer to a
double when in fact it has a pointer to a uint8_t*.
The (quick, hacky, ugly) test I used was:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
static void dump(uint8_t *var, int count) {
while(count > 0) {
printf("%02X ", *var);
var++;
count--;
}
printf("\n");
}
int main(int argc, char **argv) {
double d = 5.3265215697135e-315;
float f = (float)d;
printf("d = %1.16g: ", d);
dump((uint8_t*)&d, sizeof(d));
printf("f = %1.16g: ", f);
dump((uint8_t*)&f, sizeof(f));
(*(uint8_t*)&d) = 37;
printf("d = %1.16g: ", d);
dump((uint8_t*)&d, sizeof(d));
f = (float)d;
printf("f = %1.16g: ", f);
dump((uint8_t*)&f, sizeof(f));
(*(uint8_t*)&f) = 37;
printf("f = %1.16g: ", f);
dump((uint8_t*)&f, sizeof(f));
return 0;
}
The output on my system is:
~> gcc test.c -o test && ./test
d = 5.326521569713472e-315: 00 80 42 40 00 00 00 00
f = 0: 00 00 00 00
d = 5.326521752517761e-315: 25 80 42 40 00 00 00 00
f = 0: 00 00 00 00
f = 5.184804318001823e-44: 25 00 00 00
(The actual constant given in OP's message doesn't begin with 0x25,
but it's likely been rounded somewhat; the test demonstrates that
changing the first byte to 0x25 changes the value only slightly.)
--
Sent from my Game Boy.