Как работает этот макрос?
В этой реализации Python для микроконтроллеров они используют C-macro следующим образом:
MP_ROM_QSTR(MP_QSTR_mem16)
с:
#define MP_ROM_QSTR(q) MP_OBJ_NEW_QSTR(q)
а также:
#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 2) | 2))
Моя проблема: MP_QSTR_mem16
кажется, никогда не определяется!
Так как же это работает?
1 ответ
Макрос работает как любой макрос путем замены текста. Оригинальный код
MP_ROM_QSTR(MP_QSTR_mem16)
заменяется в два этапа, сначала сокращается до
MP_OBJ_NEW_QSTR(MP_QSTR_mem16)
который сводится к
((mp_obj_t)((((mp_uint_t)(MP_QSTR_mem16)) << 2) | 2))
Наконец, это передается компилятору C/C++.
Когда вы говорите, что термин MP_QSTR_mem16
"никогда не определяется", то это может быть правдой. Это определяется или нет, не связано с использованием этого макроса здесь. Этот макрос не должен быть определением или объявлением термина MP_QSTR_mem16
, но вместо этого это использование термина.
Макрос генерирует выражение, которое приведёт MP_QSTR_mem16
к типу mp_uint_t
, затем он сдвигает результирующее значение влево на два бита, двоично или возвращает результирующее значение с 2
и приводит результат к типу mp_obj_t
, Ничто из этого не определяет и не декларирует значение, с которого оно началось.
Возможно, вы захотите узнать, где значение MP_QSTR_mem16
должен прийти из.
РЕДАКТИРОВАТЬ
После просмотра источника, на который вы указываете, у меня также возникли проблемы с поиском декларации MP_QSTR_mem16
, Мне кажется, что термин спецификатор MP_QSTR_mem16
создается путем объединения некоторых строк. Это можно сделать в препроцессоре C/C++, используя ##
оператор. Если вы ищете MP_QSTR_ ##
в коде вы найдете несколько вхождений, подобных этому:
./micropython-master/teensy/mk20dx256_prefix.c: .name = MP_QSTR_ ## p_port ## p_pin, \
Эффективно, место, где MP_QSTR_mem16
на самом деле определяется также может выглядеть примерно так:
#define FOO(x) MP_QSTR_ ## x
(... а потом где-то...)
int FOO(mem16);
Но, несмотря на то, что искал какое-то время в источнике, я не нашел такого места. Это может быть очень злобно скрыто глубоко в макропрограмме. Подходящим способом найти место может быть настройка компилятора, чтобы выписать результат препроцессора; в этом вы сможете найти его (но это выходит за рамки темы этого вопроса, поэтому, если у вас возникли проблемы с использованием этого подхода, задайте другой вопрос).