TelluIoT / ThingML

The ThingML modelling language
https://github.com/TelluIoT/ThingML
Apache License 2.0
102 stars 32 forks source link

a negative integer value is diserialized as an unsigned int in a message #45

Closed vassik closed 8 years ago

vassik commented 10 years ago

C and C++ compilers regard an Integer type in ThingML as an unsigned int. Consider the following simple example

import "../../thingml.thingml"

thing fragment DoorWindowMsg{
    //internal messages
    message dw_state(dwstateneg : Integer, dwstatepos : Integer);
}

thing fragment DoorWindow includes DoorWindowMsg {

    provided port dwintsendport {
        sends dw_state
    }

    required port dwintrecport {
        receives dw_state
    }

    statechart behavior init IsClosedOpened {

        state IsClosedOpened {
            on entry do
                print "DoorWindow: finding out the door/window state...\n"
                dwintsendport!dw_state(get_neg(), get_pos())
            end

            transition->Ready
            event e : dwintrecport?dw_state
            action do
                'printf("Received dw_state %d %d\n", '& e.dwstateneg &', '& e.dwstatepos &');'
                'printf("Call directly %d %d \n", '& get_neg() &', '& get_pos() &');'
            end

        }

        state Ready {
            on entry do
                print "DoorWindow: ready ...\n"
            end

        }

    }
}

thing FibaroDoorWindow includes DoorWindow
@c_header "
#include <stdio.h>
"
{

    function get_neg() : Integer do
        return -10
    end

    function get_pos() : Integer do
        return 10
    end
}

configuration SampleTest
  @output_folder "/home/tmp/"
  @debug "true"
  @debug_fifo "true"
  @debug_message_send ".*"
  @debug_message_receive ".*"
{

    instance dw : FibaroDoorWindow

    // Create and connect the test app

    connector dw.dwintrecport => dw.dwintsendport
}

Integer is defined as

datatype Integer    
    @c_type "int"
    @c_byte_size "2"
    @java_type "Short"
    @SenML_type "Double"
    @ros_type "int16";

Actual output:

THINGML: Starting in debug mode...
DoorWindow: finding out the door/window state...
THINGML: -> FibaroDoorWindow_send_dwintsendport_dw_state
THINGML: <- FibaroDoorWindow_handle_dwintrecport_dw_state
Received dw_state 65526 10
Call directly -10 10 
DoorWindow: ready ...

Expected output:

THINGML: Starting in debug mode...
DoorWindow: finding out the door/window state...
THINGML: -> FibaroDoorWindow_send_dwintsendport_dw_state
THINGML: <- FibaroDoorWindow_handle_dwintrecport_dw_state
Received dw_state -10 10
Call directly -10 10 
DoorWindow: ready ...

Note: I believe the error is here

dispatch_FibaroDoorWindow_send_dwintsendport_dw_state((struct FibaroDoorWindow_Instance*)instance_by_id((mbuf[0] << 8) + mbuf[1]) /* instance */,
(mbuf[2]<<8) + mbuf[3] /* dwstateneg */ ,
(mbuf[4]<<8) + mbuf[5] /* dwstatepos */ );
brice-morin commented 10 years ago

@acartero will soon create a test about that

Hopefully, @ffleurey will fix the bug sometimes soon...

nharrand commented 8 years ago

As the serialization / de-serialization generation in c was re-written, this should no longer be a problem.

Meanwhile, I strongly recommend against the use of the type int in c when using ThingML, as its length can change depending on the hardware/compiler, and if you define int as 2 bytes long on hardware on which it is defined as 4 bytes long, you will have an issue with negative values.

In general, signed types with various length should not be used in my opinion. int16_t or int32_t should be preferred whenever it's possible.