Как перебирать объекты с динамическими именами в Cheerp/js?

Cheerp — это транспилятор C++ в js/wasm.

Используя С++, я могу взаимодействовать с объектами extern Javascript, статически определяя тип и имя объекта (и его членов).

В качестве примера возьмем следующий объект:

var example1 = {
    "itemA" : {
        value : 3
    },
    "itemB" : {
        value : 1
    },
    "item3165942" : {
        value : 4
    }
}

Было бы тривиально статически определить example1 как структуру с itemA/itemB в качестве подструктур. Но я бы никогда не смог получить доступ к example1["item3165942"].

Как динамически извлекать, индексировать и перебирать ключи/значения объекта javascript из С++? Предположим, что все элементы в example1 относятся к следующему типу:

struct item_type {
    int32_t value;
};

person Xunie    schedule 15.06.2020    source источник
comment
Что происходит, когда вы пытаетесь транспилировать некоторый итерационный код? Можете ли вы показать пример чего-то на C++, которое вы хотите преобразовать в JS?   -  person JohnFilleau    schedule 15.06.2020
comment
в этом примере показана итерация с использованием цикла for   -  person JohnFilleau    schedule 15.06.2020
comment
Вы можете использовать функцию cheerp __asm__. чтобы выполнить это. Вероятно, вы могли бы также написать функцию на стороне браузера, чтобы сделать это извлечение и вызвать ее из C++.   -  person cdhowie    schedule 15.06.2020
comment
Вот пример того, что я пытаюсь сделать. Обратите внимание, что items в моем примере определяется только внутри модели памяти C++ и полностью отделено от мира Javascript. Связанный вами пример делает следующее: он никогда не взаимодействует с какими-либо собственными объектами Javascript и просто «эмулирует» поведение vector (а не map). --- Я пытаюсь индексировать внешний собственный Javascript Object из C++ с использованием динамических ключей, очень похоже на то, как я получил бы доступ к стандартному C++ std::map<std::string, item_type>.   -  person Xunie    schedule 15.06.2020


Ответы (1)


ЕСЛИ вам нужно обрабатывать свойства с неизвестной структурой (= вы не знаете во время компиляции структуру структуры JavaScript), вам лучше перебрать ее записи:

#include <cheerp/types.h>
#include <cheerp/client.h>

namespace client
{
        struct CustomItem : public Object
        {
                int get_value();
        };
}

void enumerateProperties(client::Object* obj)
{
        auto entries = client::Object::keys(obj);
        for (int i = 0; i<entries->get_length(); i++)
        {
                client::String* K = (client::String*)(*entries)[i];
                client::CustomItem* CI = (client::CustomItem*)((*obj)[*K]);
                client::console.log(*K, CI->get_value());
        }
}

Обратите внимание, что необходимо явно выполнить два приведения: указать, что записи являются client::String*, и что сопоставленные элементы имеют тип (client::CustomItem*). Вы также должны внутри клиента пространства имен объявить, что CustomItem имеет метод get_value() (который будет скомпилирован в геттер javascript для свойства с именем «значение»).

Вы можете использовать тот же шаблон для доступа к свойствам через ["itemA"] следующим образом:

client::CustomItem * CI = (client::CustomItem*)((*obj)["itemA"]);
person Carlo Piovesan    schedule 15.06.2020
comment
enumerateProperties() принимает CustomItem*. Это правильно? Разве он не должен вместо этого использовать client::Object*? - person Xunie; 16.06.2020
comment
Говоря о динамических ситуациях: что, если я проиндексирую объект, а ключ не существует? Я получаю 0 или неопределенное поведение? - person Xunie; 16.06.2020
comment
Я не уверен, я ожидаю, что свойство будет создано и сопоставлено с неопределенным объектом. Но не рассчитывайте на это. Если вы не знаете, существует ли свойство, вы можете сначала проверить вызов obj-›hasOwnProperty(itemA), чтобы сначала убедиться, что свойство существует, и только затем индексировать его. - person Carlo Piovesan; 16.06.2020