这个宏如何工作?

时间:2017-02-13 12:15:27

标签: python c macros micropython

在微控制器的this Python implementation中,他们使用C-macro,如下所示:

@Component
@Order(Ordered.LOWEST_PRECEDENCE)
public class NoEndpointFoundEndpointMapping implements EndpointMapping {

    @Override
    public EndpointInvocationChain getEndpoint(MessageContext messageContext) throws Exception {

        throw new MyCustomException(...);
    }
}

使用:

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)) 似乎从未被定义过!

那么,这是如何工作的?

1 个答案:

答案 0 :(得分:2)

宏可以像任何宏一样通过文本替换来完成。原始代码

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是&#34;从未定义&#34;那可能是真的。它的定义与否与此宏的使用无关。此宏不应该是术语MP_QSTR_mem16定义声明,而是该术语的 use

宏生成一个表达式,将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);

但是尽管在源头搜索了一段时间我却没有找到这样的地方。它可以非常隐蔽地隐藏在宏观逻辑中。找到该位置的合适方法可以是调整编译器以写出预处理器的结果;在这个你应该能够找到它(但这远远超出了这个问题的主题,所以如果你在使用这种方法时遇到问题,请提出另一个问题)。