How to exchange strings between GUI and a device?

1,229 views
asked Mar 30, 2016 in System Integration by Customer
Is there a mechanism to transfer strings (c style char array) between the GUI and the device via a call to native code?

1 Answer

+1 vote
answered Mar 30, 2016 by Manfred Schweyer
 
Best answer

First of all, let me refer to an article that explains the basics of interfaces between a GUI application and the underlying system: Device class and device driver - How to integrate a device?

Now let's focus on the aspect of exchanging strings in both directions: 

1. Transferring a string from the GUI to native C code

Typically, a device class is the interface between the GUI application and the underlying system (as recommended in the above mentioned article). Within this device class, you can implement a command that transfers a string, for example:

method void Application::DeviceClass.SendString( arg string aText )
{
  /* the following native code is used only for target system */
  $if !$prototyper
    native ( aText )
    {
      /* just send the string to your device driver written in C */
      YourDevice_PrintString( aText );
    }
  $endif
}

If you are using a string property, just implement the onset method and transfer the string:

onset Application::DeviceClass.Name
{
  /* store the new value in the internal memory of the property */
  pure Name = value;
  
  /* the following native code is used only for target system */
  $if !$prototyper
    native ( value )
    {
      /* just send the string to your device driver written in C */
      YourDevice_SetName( value );
    }
  $endif
  
  /* notify all associated property observers */
  notifyobservers ^Name;
}

As you can see, strings are handled like other data types within a GUI project. 

Within your device driver (written in C) you can access the string very easy, because the given XString can be used as a pointer to an array with unsigned short values, which is terminated by 0x0000. This means, XString is a zero terminated 16 bit string, that can be evaluated according your needs. For example you can convert the given string into an ANSI string: 

void YourDevice_PrintString( XString aText )
{
  char    buf[ bufLen ];
  char*   ptr = buf;
  
  /* check for an empty string */
  if ( aText == 0 )
    return;

  /* read each 16-bit character and convert it to 8-bit character */
  while ( aText && *aText )
    *ptr++ = (char)(*aText++);

  /* terminate the converted string */
  *ptr = 0x00;

  /* do something with the converted string */
  printf( "The string is %s\n", buf );
}

Important notes:
Please be aware, that an empty string can be represented by a null pointer - thus, it is necessary to check always the given string!
Additionally, it is important that the given string is not stored for later usage because the Garbage Collector might free the string! If you want to keep the given string for later usage, please make your own copy!

2. Transferring a string from native C code to the GUI

For the other direction, you can implement functions within your device driver (written in C) that return an XString. The device class can later use this string like other Chora strings. 
In order to return an XString from native C code it is important that the string is created by one of the following Runtime Enviroment functions:
  EwNewString()
  EwNewStringAnsi()
  EwNewStringUtf8()
  EwNewStringUInt()
  EwNewStringInt()
  EwNewStringFloat()
  EwNewStringChar()

For example you can convert an ANSI string (received from your device) into an XString:

XString YourDevice_GetString()
{
  char*   ansiString;
  XString emwiString;

  /* read the string from somewhere of your device... */
  ansiString = ...;

  /* create an XString with the content of the ANSI string */
  emwiString = EwNewStringAnsi( ansiString );

  /* return the XString */
  return emwiString;
}

Please take care, that the ANSI string is zero terminated.

In some cases it might be interessting to create a XString with a fixed number of characters. This can be achieved by using the function EwNewStringChar( aChar, aCount ).
After creating the string, you can fill the string one character after the other. This might be helpful, if the size of the source string is unknown or the string is not terminated.

  int* sourceString            = ...;
  int  noOfSignsInSourceString = ...;
  int  i;

  /* create the XString with a fixed size */
  XString EmWiString = EwNewStringChar( 0, noOfSignsInSourceString );
  
  /* fill one character after the other into the XString */
  for ( i = 0; i < noOfSignsInSourceString; i++ )
    EmWiString[i] = (XChar)sourceString[i];

For more details concerning the different EwNewString...() functions, please have a look into the file 'ewrte.h'.

Within the device class, you can implement a simple command that reads the string from the device driver:

method string Application::DeviceClass.ReceiveString()
{
  XString text = "";
  
  /* the following native code is used only for target system */
  $if !$prototyper
    native ( text )
    {
      /* just get the string from your device driver written in C */
      text = YourDevice_GetString();
    }
  $endif
  
  return text;
}
commented Feb 27, 2017 by Christoph Friegel

FYI:
For 1. Transferring a string from the GUI to native C code you could also use EwStringToAnsi(), which converts a XString to a char*.


 

/*******************************************************************************
* FUNCTION:
*   EwStringToAnsi
*
* DESCRIPTION:
*   The function EwStringToAnsi() converts up to aCount characters from the 
*   given 16 bit wide char string aString to an 8 bit ANSI string and stores it
*   in the memory area aDest. The resulted string is terminated by the zero
*   0x00.
*
*   Character codes greater than 255 are replaced by the aDefChar value. This
*   is necessary, because the character codes in the source string can became
*   values in range 0 .. 65535. The destination string can accomodate codes
*   in the range 0 .. 255 only.
*
*   The function returns the number of converted characters incl. the last zero
*   terminator 0x00.
*
* ARGUMENTS:
*   aString  - The source 16 bit wide char string to convert.
*   aDest    - Pointer to the destination memory, where the converted 8 bit 
*     ANSI string should be stored in. This memory area has to be at least
*     aCount bytes large.
*   aCount   - The number of characters incl. the zero terminator to convert.
*   aDefChar - Default character to replace all characters, which are > 255.
*
* RETURN VALUE:
*   Returns the number of bytes written into the aDest memory area.
*
*******************************************************************************/
XInt32 EwStringToAnsi
( 
  XString           aString, 
  char*             aDest,
  XInt32            aCount,
  char              aDefChar
);

 

Ask Embedded Wizard

Welcome to the question and answer site for Embedded Wizard users and UI developers.

Ask your question and receive answers from the Embedded Wizard support team or from other members of the community!

Embedded Wizard Website | Privacy Policy | Imprint

...