0

In this Python implementation for microcontrollers, they use C-macro like follows:

MP_ROM_QSTR(MP_QSTR_mem16)

with:

#define MP_ROM_QSTR(q) MP_OBJ_NEW_QSTR(q)

and:

#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 2) | 2))

My issue is: MP_QSTR_mem16 seems to be never defined!

So, how does this work?

Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
ARF
  • 7,420
  • 8
  • 45
  • 72

1 Answers1

2

The macro works as any macros do by text replacement. The original code

MP_ROM_QSTR(MP_QSTR_mem16)

gets replaced in two steps, first it is reduced to

MP_OBJ_NEW_QSTR(MP_QSTR_mem16)

which is reduced to

((mp_obj_t)((((mp_uint_t)(MP_QSTR_mem16)) << 2) | 2))

This finally is passed to the C/C++ compiler.

When you say that the term MP_QSTR_mem16 is "never defined" then this can be true. It being defined or not is not related to the use of this macro here. This macro is not supposed to be a definition or declaration of the term MP_QSTR_mem16, but instead it is a use of the term.

The macro generates an expression which will cast MP_QSTR_mem16 to the type mp_uint_t, then it left-shifts the resulting value by two bits, binary-ors the resulting value with 2 and casts the result to the type mp_obj_t. Nothing of this defines or declares the value it started with.

You might want to find out where the value MP_QSTR_mem16 should come from.

EDIT

After having a look into the source you point to I also had trouble finding the declaration of MP_QSTR_mem16. It seems to me that the term specifier MP_QSTR_mem16 is created by concatenating some strings. This can be done in the C/C++ preprocessor using the ## operator. If you search for MP_QSTR_ ## in the code you find several occurrences like this one:

./micropython-master/teensy/mk20dx256_prefix.c:    .name = MP_QSTR_ ## p_port ## p_pin, \

Effectively, the place where MP_QSTR_mem16 is actually defined can also look something like this:

#define FOO(x) MP_QSTR_ ## x

(… and later, somewhere …)

int FOO(mem16);

But despite searching for some time in the source I did not find such a place. It can be very nastily hidden deeply within macro logic. A suitable way to find the place can be to tweak the compiler to write out the result of the preprocessor; in this you should be able to find it (but this is well beyond the topic of this question, so if you have trouble using this approach, please ask another question).

Alfe
  • 56,346
  • 20
  • 107
  • 159
  • Thanks. This put me on the right track. It appears, that a makefile calls a python script, which parses the preprocessor output to auto-generate a header file with these missing definitions. If anybody else is curious have a look at: https://github.com/micropython/micropython/blob/master/py/makeqstrdefs.py – ARF Feb 13 '17 at 14:53
  • Sounds … peculiar, to be diplomatic. Deeply disturbing was my first shot. – Alfe Feb 14 '17 at 22:17