0

The compiler is complaining about a macro defined in mjson.h

Documents\Arduino\libraries\microjson/mjson.h:135:28: error: expected primary-expression before '.' token

#define STRUCTOBJECT(s, f) .addr.offset = offsetof(s, f)

                           ^

The code compiles and links ok on Windows 7 platform running Visual Studio and Ubuntu running gcc.

The full build errors are:

Arduino: 1.8.5 (Windows 7), Board: "Arduino/Genuino Uno"

C:\Program Files (x86)\Arduino\arduino-builder -dump-prefs -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries Documents\Arduino\libraries -fqbn=arduino:avr:uno -ide-version=10805 -build-path AppData\Local\Temp\arduino_build_106446 -warnings=all -build-cache AppData\Local\Temp\arduino_cache_49629 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -prefs=runtime.tools.arduinoOTA.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -prefs=runtime.tools.avrdude.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -verbose Documents\Arduino\test_microjson\test_microjson.ino
C:\Program Files (x86)\Arduino\arduino-builder -compile -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries Documents\Arduino\libraries -fqbn=arduino:avr:uno -ide-version=10805 -build-path AppData\Local\Temp\arduino_build_106446 -warnings=all -build-cache AppData\Local\Temp\arduino_cache_49629 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -prefs=runtime.tools.arduinoOTA.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -prefs=runtime.tools.avrdude.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -verbose Documents\Arduino\test_microjson\test_microjson.ino
Using board 'uno' from platform in folder: C:\Program Files (x86)\Arduino\hardware\arduino\avr
Using core 'arduino' from platform in folder: C:\Program Files (x86)\Arduino\hardware\arduino\avr
Detecting libraries used...
"C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10805 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino" "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\standard" "AppData\Local\Temp\arduino_build_106446\sketch\test_microjson.ino.cpp" -o "nul"
"C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10805 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino" "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\standard" "-IDocuments\Arduino\libraries\microjson" "AppData\Local\Temp\arduino_build_106446\sketch\test_microjson.ino.cpp" -o "nul"
"C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10805 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino" "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\standard" "-IDocuments\Arduino\libraries\microjson" "Documents\Arduino\libraries\microjson\mjson.c" -o "nul"
Generating function prototypes...
"C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10805 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino" "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\standard" "-IDocuments\Arduino\libraries\microjson" "AppData\Local\Temp\arduino_build_106446\sketch\test_microjson.ino.cpp" -o "AppData\Local\Temp\arduino_build_106446\preproc\ctags_target_for_gcc_minus_e.cpp"
"C:\Program Files (x86)\Arduino\tools-builder\ctags\5.8-arduino11/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "AppData\Local\Temp\arduino_build_106446\preproc\ctags_target_for_gcc_minus_e.cpp"
Compiling sketch...
"C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++" -c -g -Os -Wall -Wextra -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10805 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino" "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\standard" "-IDocuments\Arduino\libraries\microjson" "AppData\Local\Temp\arduino_build_106446\sketch\test_microjson.ino.cpp" -o "AppData\Local\Temp\arduino_build_106446\sketch\test_microjson.ino.cpp.o"
In file included from Documents\Arduino\test_microjson\test_microjson.ino:7:0:

Documents\Arduino\libraries\microjson/mjson.h:135:28: error: expected primary-expression before '.' token

 #define STRUCTOBJECT(s, f) .addr.offset = offsetof(s, f)

                            ^

Documents\Arduino\test_microjson\test_microjson.ino:31:29: note: in expansion of macro 'STRUCTOBJECT'

   { "start_pin", t_integer, STRUCTOBJECT(lights_t, start_pin) },

                             ^

Documents\Arduino\libraries\microjson/mjson.h:135:28: error: expected primary-expression before '.' token

 #define STRUCTOBJECT(s, f) .addr.offset = offsetof(s, f)

                            ^

Documents\Arduino\test_microjson\test_microjson.ino:32:27: note: in expansion of macro 'STRUCTOBJECT'

   { "end_pin", t_integer, STRUCTOBJECT(lights_t, end_pin) },

                           ^

Documents\Arduino\libraries\microjson/mjson.h:135:28: error: expected primary-expression before '.' token

 #define STRUCTOBJECT(s, f) .addr.offset = offsetof(s, f)

                            ^

Documents\Arduino\test_microjson\test_microjson.ino:33:30: note: in expansion of macro 'STRUCTOBJECT'

   { "colour_red", t_integer, STRUCTOBJECT(lights_t, colour_red) },

                              ^

Documents\Arduino\libraries\microjson/mjson.h:135:28: error: expected primary-expression before '.' token

 #define STRUCTOBJECT(s, f) .addr.offset = offsetof(s, f)

                            ^

Documents\Arduino\test_microjson\test_microjson.ino:34:32: note: in expansion of macro 'STRUCTOBJECT'

   { "colour_green", t_integer, STRUCTOBJECT(lights_t, colour_green) },

                                ^

Documents\Arduino\libraries\microjson/mjson.h:135:28: error: expected primary-expression before '.' token

 #define STRUCTOBJECT(s, f) .addr.offset = offsetof(s, f)

                            ^

Documents\Arduino\test_microjson\test_microjson.ino:35:31: note: in expansion of macro 'STRUCTOBJECT'

   { "colour_blue", t_integer, STRUCTOBJECT(lights_t, colour_blue) },

                               ^

test_microjson:40: error: expected primary-expression before '.' token

   { "type", t_string, .addr.string = thenode.type, .len = sizeof(thenode.type) },

                       ^

In file included from Documents\Arduino\test_microjson\test_microjson.ino:7:0:

Documents\Arduino\libraries\microjson/mjson.h:137:2: error: expected primary-expression before '.' token

  .addr.array.element_type = t_structobject, \

  ^

Documents\Arduino\test_microjson\test_microjson.ino:41:26: note: in expansion of macro 'STRUCTARRAY'

   { "sections", t_array, STRUCTARRAY(thenode.thelight, section_attrs, &num_sections) },

                          ^

Documents\Arduino\libraries\microjson/mjson.h:138:2: error: expected primary-expression before '.' token

  .addr.array.arr.objects.subtype = e, \

  ^

Documents\Arduino\test_microjson\test_microjson.ino:41:26: note: in expansion of macro 'STRUCTARRAY'

   { "sections", t_array, STRUCTARRAY(thenode.thelight, section_attrs, &num_sections) },

                          ^

Documents\Arduino\libraries\microjson/mjson.h:139:2: error: expected primary-expression before '.' token

  .addr.array.arr.objects.base = (char*)a, \

  ^

Documents\Arduino\test_microjson\test_microjson.ino:41:26: note: in expansion of macro 'STRUCTARRAY'

   { "sections", t_array, STRUCTARRAY(thenode.thelight, section_attrs, &num_sections) },

                          ^

Documents\Arduino\libraries\microjson/mjson.h:140:2: error: expected primary-expression before '.' token

  .addr.array.arr.objects.stride = sizeof(a[0]), \

  ^

Documents\Arduino\test_microjson\test_microjson.ino:41:26: note: in expansion of macro 'STRUCTARRAY'

   { "sections", t_array, STRUCTARRAY(thenode.thelight, section_attrs, &num_sections) },

                          ^

Documents\Arduino\libraries\microjson/mjson.h:141:2: error: expected primary-expression before '.' token

  .addr.array.count = n, \

  ^

Documents\Arduino\test_microjson\test_microjson.ino:41:26: note: in expansion of macro 'STRUCTARRAY'

   { "sections", t_array, STRUCTARRAY(thenode.thelight, section_attrs, &num_sections) },

                          ^

Documents\Arduino\libraries\microjson/mjson.h:142:2: error: expected primary-expression before '.' token

  .addr.array.maxlen = (int)(sizeof(a)/sizeof(a[0]))

  ^

Documents\Arduino\test_microjson\test_microjson.ino:41:26: note: in expansion of macro 'STRUCTARRAY'

   { "sections", t_array, STRUCTARRAY(thenode.thelight, section_attrs, &num_sections) },

                          ^

Using library microjson in folder: Documents\Arduino\libraries\microjson (legacy)
exit status 1
expected primary-expression before '.' token

test_microjson.ino:

#include <stdlib.h>
#include <stdbool.h>

#include <stddef.h>  // offsetof - used in STRUCTOBJECT macro

#include <mjson.h>

#define MAX_SECTIONS 6  // we support up to six different sections on strip

// in json sections is an array of these light options
typedef struct light_section {
  int start_pin;
  int end_pin;
  int colour_red;
  int colour_green;
  int colour_blue;
}lights_t;


typedef struct node {
  char type[20];
  lights_t thelight[MAX_SECTIONS];
} node_t;

node_t thenode;

static int num_sections;

const struct json_attr_t section_attrs[] = {
  { "start_pin", t_integer, STRUCTOBJECT(lights_t, start_pin) },
  { "end_pin", t_integer, STRUCTOBJECT(lights_t, end_pin) },
  { "colour_red", t_integer, STRUCTOBJECT(lights_t, colour_red) },
  { "colour_green", t_integer, STRUCTOBJECT(lights_t, colour_green) },
  { "colour_blue", t_integer, STRUCTOBJECT(lights_t, colour_blue) },
  { NULL },
};

static const struct json_attr_t json_attrs[] = {
  { "type", t_string, .addr.string = thenode.type, .len = sizeof(thenode.type) },
  { "sections", t_array, STRUCTARRAY(thenode.thelight, section_attrs, &num_sections) },
  { NULL },
};


void setup() {

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  // this check is only needed on the Leonardo:
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  // start the Ethernet connection:
  Serial.println("microjson test");

  static const char *s =
    "{ \"type\": \"section\", \"sections\": [{ \"start_pin\": 0, \"end_pin\": 71, \"colour_red\": 0, \"colour_green\": 255, \"colour_blue\": 0 }, { \"start_pin\": 216, \"end_pin\": 287, \"colour_red\": 255, \"colour_green\": 0, \"colour_blue\": 0 }] }";

  int status = json_read_object(s, json_attrs, NULL);

  if (status != 0)
    Serial.println(json_error_string(status));

  Serial.print("found ");
  Serial.print(num_sections);
  Serial.print(" sections");

  Serial.print("type=");
  Serial.println(thenode.type);

  //printf("type=%s\n", thenode.type);
  for (int i = 0; i < num_sections; ++i) {
    Serial.print("section [");
    Serial.print(i);
    Serial.print("]: start_pin=");
    Serial.print(thenode.thelight[i].start_pin);
    Serial.print(", end_pin=");
    Serial.print(thenode.thelight[i].end_pin);
    Serial.print(", red=");
    Serial.print(thenode.thelight[i].colour_red);
    Serial.print(", green=");
    Serial.print(thenode.thelight[i].colour_green);
    Serial.print(", blue=");
    Serial.println(thenode.thelight[i].colour_blue);    
  }
}

void loop() {
  // put your main code here, to run repeatedly:

}

And the offending macro in mjson.h STRUCTOBJECT. And also STRUCTARRAY. Here they are:

 * Use the following macros to declare template initializers for structobject
 * arrays.  Writing the equivalents out by hand is error-prone.
 *
 * STRUCTOBJECT takes a structure name s, and a fieldname f in s.
 *
 * STRUCTARRAY takes the name of a structure array, a pointer to a an
 * initializer defining the subobject type, and the address of an integer to
 * store the length in.
 */
#define STRUCTOBJECT(s, f)  .addr.offset = offsetof(s, f)
#define STRUCTARRAY(a, e, n) \
    .addr.array.element_type = t_structobject, \
    .addr.array.arr.objects.subtype = e, \
    .addr.array.arr.objects.base = (char*)a, \
    .addr.array.arr.objects.stride = sizeof(a[0]), \
    .addr.array.count = n, \
    .addr.array.maxlen = (int)(sizeof(a)/sizeof(a[0]))

How can I fix this to get it to compile using Arduino avr-g++ ?

mjson.h is from microjson library. I can provide more details of that if required.

mjson.h header:

/* Structures for JSON parsing using only fixed-extent memory
 *
 * This file is Copyright (c) 2014 by Eric S. Raymond.
 * BSD terms apply: see the file COPYING in the distribution root for details.
 */

#include <stdbool.h>
#include <ctype.h>
#include <stdio.h>
#include <sys/types.h>

#define NITEMS(x) (int)(sizeof(x)/sizeof(x[0]))

typedef enum {t_integer, t_uinteger, t_real,
          t_string, t_boolean, t_character,
          t_time,
          t_object, t_structobject, t_array,
          t_check, t_ignore} 
    json_type;

struct json_enum_t {
    char    *name;
    int     value;
};

struct json_array_t {
    json_type element_type;
    union {
      struct {
        const struct json_attr_t *subtype;
        char *base;
        size_t stride;
      } objects;
      struct {
        char **ptrs;
        char *store;
        int storelen;
      } strings;
      struct {
        int *store;
      } integers;
      struct {
        unsigned int *store;
      } uintegers;
      struct {
        double *store;
      } reals;
      struct {
        bool *store;
      } booleans;
    } arr;
    int *count, maxlen;
};

struct json_attr_t {
    char *attribute;
    json_type type;

    union {
      int *integer;
      unsigned int *uinteger;
      double *real;
      char *string;
      bool *boolean;
      char *character;
      struct json_array_t array;
      size_t offset;
    } addr;

    union {
      int integer;
      unsigned int uinteger;
      double real;
      bool boolean;
      char character;
      char *check;
    } dflt;

    size_t len;
    const struct json_enum_t *map;
    bool nodefault;
};

#define JSON_ATTR_MAX   31  /* max chars in JSON attribute name */
#define JSON_VAL_MAX    512 /* max chars in JSON value part */

#ifdef __cplusplus
extern "C" {
#endif
int json_read_object(const char *, const struct json_attr_t *,
             /*@null@*/const char **);
int json_read_array(const char *, const struct json_array_t *,
            /*@null@*/const char **);
const /*@observer@*/char *json_error_string(int);

void json_enable_debug(int, FILE *);
#ifdef __cplusplus
}
#endif

#define JSON_ERR_OBSTART    1   /* non-WS when expecting object start */
#define JSON_ERR_ATTRSTART  2   /* non-WS when expecting attrib start */
#define JSON_ERR_BADATTR    3   /* unknown attribute name */
#define JSON_ERR_ATTRLEN    4   /* attribute name too long */
#define JSON_ERR_NOARRAY    5   /* saw [ when not expecting array */
#define JSON_ERR_NOBRAK     6   /* array element specified, but no [ */
#define JSON_ERR_STRLONG    7   /* string value too long */
#define JSON_ERR_TOKLONG    8   /* token value too long */
#define JSON_ERR_BADTRAIL   9   /* garbage while expecting comma or } or ] */
#define JSON_ERR_ARRAYSTART 10  /* didn't find expected array start */
#define JSON_ERR_OBJARR     11  /* error while parsing object array */
#define JSON_ERR_SUBTOOLONG 12  /* too many array elements */
#define JSON_ERR_BADSUBTRAIL    13  /* garbage while expecting array comma */
#define JSON_ERR_SUBTYPE    14  /* unsupported array element type */
#define JSON_ERR_BADSTRING  15  /* error while string parsing */
#define JSON_ERR_CHECKFAIL  16  /* check attribute not matched */
#define JSON_ERR_NOPARSTR   17  /* can't support strings in parallel arrays */
#define JSON_ERR_BADENUM    18  /* invalid enumerated value */
#define JSON_ERR_QNONSTRING 19  /* saw quoted value when expecting nonstring */
#define JSON_ERR_NONQSTRING 19  /* didn't see quoted value when expecting string */
#define JSON_ERR_MISC       20  /* other data conversion error */
#define JSON_ERR_BADNUM     21  /* error while parsing a numerical argument */
#define JSON_ERR_NULLPTR    22  /* unexpected null value or attribute pointer */

/*
 * Use the following macros to declare template initializers for structobject
 * arrays.  Writing the equivalents out by hand is error-prone.
 *
 * STRUCTOBJECT takes a structure name s, and a fieldname f in s.
 *
 * STRUCTARRAY takes the name of a structure array, a pointer to a an
 * initializer defining the subobject type, and the address of an integer to
 * store the length in.
 */
#define STRUCTOBJECT(s, f)  .addr.offset = offsetof(s, f)
#define STRUCTARRAY(a, e, n) \
    .addr.array.element_type = t_structobject, \
    .addr.array.arr.objects.subtype = e, \
    .addr.array.arr.objects.base = (char*)a, \
    .addr.array.arr.objects.stride = sizeof(a[0]), \
    .addr.array.count = n, \
    .addr.array.maxlen = (int)(sizeof(a)/sizeof(a[0]))

/* json.h ends here */
1
  • why do you want to use this library with Arduino?
    – Juraj
    Commented Mar 18, 2018 at 16:40

1 Answer 1

1

.ino is compiled as C++. your test is C code. put the C code in a .c file and the declaration in .h file and include the .h in .ino

I created a test.c, copied the content of your main.c into it and renamed the main function to test().

Then I created a test.h with

#ifndef test_h
#define test_h

extern "C" void test(char * buff);

#endif

and in ino setup() I call test();

it compiles. It runs. Output:

2 sections
type=section
section [0]: start_pin=  0, end_pin= 71, red=  0, green=255, blue=  0
section [1]: start_pin=216, end_pin=287, red=255, green= 53, blue=  0

in ino

void setup()
{
  Serial.begin(115200);
  char buff[700];
  test(buff);
  Serial.print(buff);
}

in .c

void test(char* buff) {

  static const char *s =
      "{ \"type\": \"section\", \"sections\": [{ \"start_pin\": 0, \"end_pin\": 71, \"colour_red\": 0, \"colour_green\": 255, \"colour_blue\": 0 }, { \"start_pin\": 216, \"end_pin\": 287, \"colour_red\": 255, \"colour_green\": 0, \"colour_blue\": 0 }] }";

  int status = json_read_object(s, json_attrs, NULL);

  if (status != 0) {
    sprintf(buff, json_error_string(status));
    return;
  }

  int pos = sprintf(buff, "%d sections\n", num_sections);

  pos += sprintf(buff + pos, "type=%s\n", thenode.type);
  for (int i = 0; i < num_sections; ++i) {
    pos +=
        sprintf(buff + pos,
            "section [%d]: start_pin=%3d, end_pin=%3d, red=%3d, green=%3d, blue=%3d\n",
            i, thenode.thelight[i].start_pin, thenode.thelight[i].end_pin,
            thenode.thelight[i].colour_red, thenode.thelight[i].colour_green,
            thenode.thelight[i].colour_blue);
  }
}
6
  • Sorry about the confusion, I uploaded wrong exercising code. Changed now to code I used in ino file Commented Mar 18, 2018 at 17:22
  • Do I put the test.h and test.c in the same folder as the test_microjson.ino or would I put in same folder as /Android/libraries/microjson ? Commented Mar 18, 2018 at 18:04
  • to project folder. to .ino.
    – Juraj
    Commented Mar 18, 2018 at 18:08
  • Better but getting multiple definition of `test' at link stage now. Actually changed to testmj and now just getting error multiple definition of section_attrs Commented Mar 18, 2018 at 18:23
  • add guard #ifdef to mjson.h and test.h. en.wikipedia.org/wiki/Include_guard
    – Juraj
    Commented Mar 18, 2018 at 18:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.