Как работает этот макрос?

В этой реализации 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);

Но, несмотря на то, что искал какое-то время в источнике, я не нашел такого места. Это может быть очень злобно скрыто глубоко в макропрограмме. Подходящим способом найти место может быть настройка компилятора, чтобы выписать результат препроцессора; в этом вы сможете найти его (но это выходит за рамки темы этого вопроса, поэтому, если у вас возникли проблемы с использованием этого подхода, задайте другой вопрос).

Другие вопросы по тегам