アリIot SDKの登録コールバック分析

5432 ワード

コールバック関数の登録は3つのマクロで実現し、巧みに##で関数をつなぎ合わせた.
#define IOT_RegisterCallback(evt, cb)           iotx_register_for_##evt(cb)
#define DECLARE_EVENT_CALLBACK(evt, cb)         int iotx_register_for_##evt(cb);
#define DEFINE_EVENT_CALLBACK(evt, cb)          int iotx_register_for_##evt(cb) { \
        if (evt < 0 || evt >= sizeof(g_impl_event_map)/sizeof(impl_event_map_t)) {return -1;} \
        g_impl_event_map[evt].callback = (void *)callback;return 0;}

 
int everything_state_handle(const int state_code, const char * state_message)
{
    EXAMPLE_TRACE("code: -0x%04x, message: %s", -state_code, state_message);
    return 0;
}
IOT_RegisterCallback(ITE_STATE_EVERYTHING, everything_state_handle);

コールバック関数を登録すると、次のマクロが呼び出されます.
#define IOT_RegisterCallback(evt, cb)           iotx_register_for_##evt(cb)

マクロが展開されるとiotx_が直接呼び出されます.register_for_ITE_STATE_EVERYTHING、入力パラメータeverything_state_handle
実は関数呼び出しです
iotx_register_for_ITE_STATE_EVERYTHING(everything_state_handle);

つまり、次の関数を呼び出します.次の関数は、すべての機能(impl_event_map_t g_impl_event_map[]というデータ型に定義されています)をこのコールバックに登録します.つまり、次のいずれかの機能イベントがトリガーされ、転送されたcallbackが呼び出されます.
関数の定義は次のとおりです.
int iotx_register_for_ITE_STATE_EVERYTHING(state_handler_t callback)
{
    int idx = 0;

    for (idx = ITE_STATE_EVERYTHING; idx <= ITE_STATE_DEV_MODEL; idx++) {
        g_impl_event_map[idx].callback = (void *)callback;
    }

    return 0;
}
typedef struct {
    int eventid;
    void *callback;
} impl_event_map_t;

static impl_event_map_t g_impl_event_map[] = {
    {ITE_AWSS_STATUS,          NULL},
    {ITE_CONNECT_SUCC,         NULL},
    {ITE_CONNECT_FAIL,         NULL},
    {ITE_DISCONNECTED,         NULL},
    {ITE_RAWDATA_ARRIVED,      NULL},
    {ITE_SERVICE_REQUEST,      NULL},
    {ITE_SERVICE_REQUEST_EXT,  NULL},
    {ITE_PROPERTY_SET,         NULL},
    {ITE_PROPERTY_GET,         NULL},
#ifdef DEVICE_MODEL_SHADOW
    {ITE_PROPERTY_DESIRED_GET_REPLY,         NULL},
#endif
    {ITE_REPORT_REPLY,         NULL},
    {ITE_TRIGGER_EVENT_REPLY,  NULL},
    {ITE_TIMESTAMP_REPLY,      NULL},
    {ITE_TOPOLIST_REPLY,       NULL},
    {ITE_PERMIT_JOIN,          NULL},
    {ITE_INITIALIZE_COMPLETED, NULL},
    {ITE_FOTA,                 NULL},
    {ITE_COTA,                 NULL},
    {ITE_MQTT_CONNECT_SUCC,    NULL},
    {ITE_CLOUD_ERROR,          NULL},
    {ITE_DYNREG_DEVICE_SECRET, NULL},
    {ITE_IDENTITY_RESPONSE,    NULL},
    {ITE_STATE_EVERYTHING,     NULL},
    {ITE_STATE_USER_INPUT,     NULL},
    {ITE_STATE_SYS_DEPEND,     NULL},
    {ITE_STATE_MQTT_COMM,      NULL},
    {ITE_STATE_WIFI_PROV,      NULL},
    {ITE_STATE_COAP_LOCAL,     NULL},
    {ITE_STATE_HTTP_COMM,      NULL},
    {ITE_STATE_OTA,            NULL},
    {ITE_STATE_DEV_BIND,       NULL},
    {ITE_STATE_DEV_MODEL,      NULL}
};

だからこのIOT_RegisterCallback(ITE_STATE_EVERYTHING, everything_state_handle);デバッグ用のはずですが、各機能がトリガーされるとeverythingが呼び出されます.state_handle
 
同様に、次の関数はiotx_を呼び出すはずです.register_for_ITE_IDENTITY_RESPONSE(identity_response_handle);
しかし、この関数は見つかりませんでした.プリコンパイルで生成されました.マクロで定義
int identity_response_handle(const char *payload)
{
    EXAMPLE_TRACE("identify: %s", payload);

    return 0;
}
IOT_RegisterCallback(ITE_IDENTITY_RESPONSE, identity_response_handle);

 
さらに下を見るとマクロ定義があります
#define DECLARE_EVENT_CALLBACK(evt, cb)         int iotx_register_for_##evt(cb);

そうです.このマクロ定義で関数iotx_を宣言します.register_for_ITE_IDENTITY_RESPONSE()
宣言int iotx_register_for_ITE_IDENTITY_RESPONSE( int (*cb)(const char *));
DECLARE_EVENT_CALLBACK(ITE_IDENTITY_RESPONSE,    int (*cb)(const char *))

宣言int iotx_register_for_ITE_STATE_EVERYTHING(state_handler_t cb);
typedef int (*state_handler_t)(const int state_code, const char *state_message);
DECLARE_EVENT_CALLBACK(ITE_STATE_EVERYTHING, state_handler_t cb);

上記の関数を定義するマクロもあります.
#define DEFINE_EVENT_CALLBACK(evt, cb)          int iotx_register_for_##evt(cb) { \
        if (evt < 0 || evt >= sizeof(g_impl_event_map)/sizeof(impl_event_map_t)) {return -1;} \
        g_impl_event_map[evt].callback = (void *)callback;return 0;}

これらの関数定義はinfra_compat.cで定義し、mqtt_を抽出するexample.cで使った解析
DEFINE_EVENT_CALLBACK(ITE_IDENTITY_RESPONSE,    int (*callback)(const char *))

マクロを置き換えると、次のようになります.
int iotx_register_for_ITE_IDENTITY_RESPONSE( int (*callback)(const char *) )
{
     if (ITE_IDENTITY_RESPONSE< 0 || ITE_IDENTITY_RESPONSE>= sizeof(g_impl_event_map)/sizeof(impl_event_map_t))
     {
         return -1;
     }
     g_impl_event_map[evt].callback = (void *)callback;
     
     return 0;
}

この関数は指定されたコールバック関数の登録を担当し、ITE_が発生します.IDENTITY_RESPONSEイベントの場合、転送されたcallbackが呼び出されます.
この関数は指定したコールバック関数を返し、呼び出し者に呼び出されます.
void *iotx_event_callback(int evt)
{
    if (evt < 0 || evt >= sizeof(g_impl_event_map) / sizeof(impl_event_map_t)) {
        return NULL;
    }
    return g_impl_event_map[evt].callback;
}

呼び出し形式
void *callback = NULL;

callback = iotx_event_callback(ITE_IDENTITY_RESPONSE);
if (callback)
{
    ((int (*)(const char*))callback)(payload);
}