LINUX.ORG.RU

C++ Вопросик.


0

0

Возможно ли в плюсах создать(точнее объявить, а потом создать) например структуру в Run-Time?

Т.е. сервер получает char[] из которого парсит, что ему нужна структура типа struct
{
int;
float;
bla-bla...
};

Можно ли сделать такое в runtime?

Надеюсь я доступн описал проблему:)

Структуры всё время разные и программа узнаёт о них по приходящим время от времяни данным.

golodranez ★★★★
() автор топика

Создавать придётся в куче, и без горы костылей не обойтись. А так, вроде-бы, фундаментальных запретов на подобное безобразие в плюсах не припомню.

one_more_hokum ★★★
()

В простейшем случае, можбыть, удастся обойтись RTTI, а если чего странного захочется -- то ручками, ручками. Костыли, тысячи их!!!

one_more_hokum ★★★
()
Ответ на: комментарий от golodranez

>Структуры всё время разные и программа узнаёт о них по приходящим время от времяни данным.

Формируешь по сигнатуре массив вариантов, в котором каждый элемент, в свою очередь, может быть вложенным массивом вариантов - творческая задача на час. Можно Питон заэмбедить - там можно генерить питоновские типы по питоновской сигнатуре в виде строки символов. Строгая типизация в понимании С++ тебе тут не поможет.

Absurd ★★★
()
Ответ на: комментарий от golodranez

> времяни

бл..ть

надо делать описание структурыти па

#define F_INT 1 #define F_FLOAT 2

typedef struct { int type; int pos; } td_t;

typedef struct { int n_fields; td_t* fields; char* buffer; } st_t;

st.fields[0].type = F_INT; st.fields[0].pos = 0; st.fields[0].type = F_FLOAT; st.fields[0].pos = 4;

и т.д. ...

имхо

anonymous
()
Ответ на: комментарий от anonymous

но вообще если структур разных небольшое количество, лучше их сразу сначла всех описать, а оптом делать только (struct_blabla*)buffer?

anonymous
()

Ближайшее, что можно - завести хеш-таблицу. Обычную структуру в плюсовом смысле не получится - во всяком случае, запихать ее в сигнатуры функций в рантайме вряд ли удастся.

Правда, можно пытаться на лету генерить .so-шки, но это для совсем сильных духом

Вообще непонятна постановка задачи - ведь обычная структура в рантайме это только кусок памяти. А members это то, что использует компилятор как смещения относительно начала структуры. Распихать данные в выделенный кусок памяти - не проблема. А вот как дальше с ними работать?

svu ★★★★★
()
Ответ на: комментарий от anonymous

Не совсем понятно - что после делать с этой полученной структурой?

Ведь, что бы с каждой новой структурой работать, надо уже весь код в рантайме генерировать... :)

anonymous
()
Ответ на: комментарий от anonymous

>но вообще если структур разных небольшое количество, лучше их сразу сначла всех описать, а оптом делать только (struct_blabla*)buffer?

еслиб структур былобы небольшое количествао, то вопрос бы не стоял

golodranez ★★★★
() автор топика
Ответ на: комментарий от svu

>Распихать данные в выделенный кусок памяти - не проблема. А вот как дальше с ними работать?

вот-вот..

>Ближайшее, что можно - завести хеш-таблицу.

Можно подробней, чтото я не догоню. map?

golodranez ★★★★
() автор топика
Ответ на: комментарий от golodranez

Ну да, map. Только там надо хитро хранить - не просто "имя"-"значение", но еще чтобы значение можно было исследовать при помощи rtti - чтоб строки от чисел отличать и пр...

svu ★★★★★
()

Я тоже не догоняю, зачем это надо. Типизированные структуры нужны для проверки типов во время компиляции. Проверка типов во время выполнения доступна только в динамически типизированных языках. В С++ этого не добиться. Поэтому, видимо, самый правильный путь - выделять массив байтов нужного размера и руками отмерять оффсеты и размеры.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

Вот эти два варианта и рассматриваю. С Boost'ом связаваться не охота, как там с ним дела на RH7.3, фиг его знает. А переться в Китай ели там чего не запашет нормально не охота.

golodranez ★★★★
() автор топика

>Можно ли сделать такое в runtime?

Да, можно.

Выделяете себе память и пишете туда данные как хотите. Зная смещение каждого члена структуры от начала выделенного блока памяти, получаете доступ.

Учтите только, что это - хождение по очень тонкому льду.

anonymous
()
Ответ на: комментарий от anonymous

>Учтите только, что это - хождение по очень тонкому льду.

У меня вся программа по такому льду ходит и все возможные неприятности я знаю досконально:)

golodranez ★★★★
() автор топика
Ответ на: комментарий от Cy6erBr4in

>Это называется Мета класс :) и вам в сторону метапрограммирования, велкам ту лисп ворлд! :))

Я рассказывал начальству про лисп, но они не оценили)) Угрожают послать всю команду на курсы по жабе :)))) Говорят:"Интерпайз! И ниипёт!"))))

golodranez ★★★★
() автор топика

первое, что пришло в глову - хранить таблицу указателей на разные функции для установки/чтения разных полей и прочих операций...
например:

для присланной struct { int a; double b; char c[7];};
создавать массив

struct {
void * data;
unsigned length;
struct {
unsigned offset;
...
} fields[0];
};
} bla ={
data,19,
{0,...}
{4,...}
{12,..}
};

функции абстрагируются в зависимости от того, что тебе надо с этими структурами делать

xydo ★★
()
Ответ на: комментарий от golodranez

> У меня вся программа по такому льду ходит и все возможные неприятности я знаю досконально:)

На месте вашего руководителя я бы уволил вас за такое без выходного пособия.

// pppp

anonymous
()
Ответ на: комментарий от anonymous

Можно посмотреть как передаются данные в протоколе XML-RPC, в том числе и структуры. Если нужна бинарная реализация (а не текстовая как в XML-RPC) - посмотрите как это делает CORBA Еще один вариант - подключить один из скриптовых языков (TCL, lua, python) и передавать текстовой строкой не только данные - но и целые куски программы!

anonymous
()
Ответ на: комментарий от anonymous

> Можно посмотреть как передаются данные в протоколе XML-RPC, в том числе и структуры. Если нужна бинарная реализация (а не текстовая как в XML-RPC) - посмотрите как это делает CORBA Еще один вариант - подключить один из скриптовых языков (TCL, lua, python) и передавать текстовой строкой не только данные - но и целые куски программы!

а ещё лучше не мучаться, а взять CL

shild
()
Ответ на: комментарий от Legioner

> Проверка типов во время выполнения доступна только в динамически типизированных языках. В С++ этого не добиться.

Можно добиться, причем очень просто. Даже не обязательно boost.

Пишется один класс и 2 шаблончика:

#include <iostream>

class Something
{
  /// это корень иерархии, можно написать нужные пустые вирутальные методы, например print
public:
  virtual void print_value_size() {};
};

template<typename T> class Boxed: public Something
{
private:
  T value;
public:
  Boxed<T>(T arg): value(arg) {}
  T get() { return value; }
  virtual void print_value_size() { std::cout << sizeof(value) << '\n'; }
};

template<typename T> inline Boxed<T>* boxed(T arg) { return new Boxed<T>(arg); }

/// usage:
int main()
{
  Something* x[]={ boxed(1), boxed("asdf"), boxed(3.0) };
  for( int i=0; i<3; i++)
    x[i]->print_value_size();
}

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

И где здесь проверка типов во время выполнения?

Я, конечно, ерунду написал, проверка типов во время выполнения делается тривиально - хранить рядом с каждым значением его тип в виде некоторого идентификатора и проверять где нужно (как в динамически типизируемых языках, собственно, и делается). Если типы исчёрпываются примитивными (строка, число, ...), то проблем не будет. Если типы могут быть составными, массивами, структурами, ссылками, уже будет сложно.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

> И где здесь проверка типов во время выполнения?

Нда... почитай что-нить по виртуальным функциям в плюсах, прежде чем делать заявления "в С++ невозможно ХХХ".

Тут не предполагается проверки *во время выполнения*, хотя ее тоже можно легко в несколько строк написать для любых составных типов, в т.ч. классов.

Тут предполагается именно статическая проверка, которую может делать компилятор, и при этом операции на забоксенных типах будут вызываться *динамически*, а именно это практически всегда и надо.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от golodranez

На яве кстати с этим проще.

Но ваша проблемасходна с проблемой при создании биндингов к 
нетипизированным языкам. Выше уже приводили код, но на всякий случай 
посмотрите реализацию типа variant (например в winapi) который может 
хранить любые данные, подозреваю что в бусте также.

struct Variant{
    int type; // тип значение, уславливаетесть что 0 - int, 1 - char и тп
    union Value {
        int intValue;
        char charValue;        
        //и тп.  
    } value; // а тут в поле соотв. типу храним значение    
};

Соответственно ваша структура будет представлять собой массив таких 
variant, реализацию лучше подглядите в винапи или еще где ибо я писал 
по памяти, а виде я его последний раз в 2006 скорее всего чтото и 
забыл.

wfrr ★★☆
()
Ответ на: комментарий от www_linux_org_ru

Любители С☦☦ такие смешные когда городят свои костыли - они дерутся за право считать свой костыль более костылистым.

ps. Твой изврат не будет работать из модуля, также он добавляет лишние сущньсти. Приятного аппетиту кактусоедик.

wfrr ★★☆
()
Ответ на: комментарий от wfrr

> Твой изврат не будет работать из модуля, также он добавляет лишние сущньсти. Приятного аппетиту кактусоедик.

А ты, белка, продолжай есть как^W^W использовать union не по назначению :-)

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от wfrr

> Твой изврат не будет работать из модуля,

И раз уж ты разогрел машину времени, так скажи, в каком году в gcc, icc & msvc появилась поддержка модулей?

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

Это я к тому, что в текущем стандарте плюсов модулей нет, и, насколько мне известно, в С++0х их не предполагают вводить (хотя драфт конечно может поменяться).

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> ... C++ cruft skipped ...

Ты забыл самое главное - как сгенерить инстанс структуры по сигнатуре заданной в виде строки символов.

Absurd ★★★
()
Ответ на: комментарий от www_linux_org_ru

Все это здорово, но какое отношение имеет к поставленному вначале вопросу?

Автору надо на лету (на этапе выполнения) создавать новые структуры, а не работать с некоторым, жестко заданным на этапе компиляции, перечнем структур.

anonymous
()
Ответ на: комментарий от www_linux_org_ru

>И все это без костылей.

И все это не по теме.

anonymous
()
Ответ на: комментарий от anonymous

> Автору надо на лету (на этапе выполнения) создавать новые структуры,

Да, мой подход ЭТО позволяет

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от anonymous

> Автору надо на лету (на этапе выполнения) создавать новые структуры,

Если тебе надо обращаться к полям новосозданной структуры по именам, а не по номеру (как у меня в примере), то используй map<const char*, Something*> вместо массива.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

Пример конечно интересный, но структуру он не создает (и не показывает как это сделать).

Автор топика видимо хочет использовать что-то типа этого: void * buf = getData(); static_cast<our_dynamically_generated_struct *>(buf)->getSomething;

С помощью этого примера такого не добиться

P1XeL
()
Ответ на: комментарий от P1XeL

> static_cast<our_dynamically_generated_struct *>(buf)

Это будет *не* портабельно (хотя бы endianness)

Кроме того, *кто* создал эти бинарные данные getData()?

А. Это какой-то чужой формат типа jpeg+exif, tiff, udp пакет... -- тогда его надо просто распарсить и привести к нормальному "статически-классовому" виду.

Б. Это записала эта же программа... ну тогда элементарно переделываем мой пример, чтобы он сериализовался и обратно читался, причем *без* этих static_cast-ов.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от Absurd

> Ты забыл самое главное - как сгенерить инстанс структуры по сигнатуре заданной в виде строки символов.

Я не понял -- зачем по сигнатуре. Ты имеешь в виду распарсить строку?

Но по-моему это очевидно: Something* parse( char* & ptr ) {...}

Могу написать микро-пример. Допустим, "i0sАs7d7\0" парсится в int 0, "А\0", "7\0", double 7 (для простоты как описатель типа, так и значение занимает ровно 1 байт).

www_linux_org_ru ★★★★★
()

Автор, в плюсах, с их статичностью и, конкретно, статичным недо-ооп, такое можно сделать разве что через кучу костылей. Если тебе нужны подобные возможности, используй нормальные языки и не еби мозг.

anonymous
()
Ответ на: комментарий от anonymous

>На месте вашего руководителя я бы уволил вас за такое без выходного пособия.

Ты вообще на Си программировал, умник? Соси жабу иди.

golodranez ★★★★
() автор топика
Ответ на: комментарий от anonymous

>На месте вашего руководителя я бы уволил вас за такое без выходного пособия.

подскажи нормальные языки с нормальны ооп

golodranez ★★★★
() автор топика
Ответ на: комментарий от golodranez

>> На месте вашего руководителя я бы уволил вас за такое без выходного пособия.

> подскажи нормальные языки с нормальны ооп

Анонимус имел в виду расплату за "постоянное хождение по тонкому льду". С++ имеет достаточно динамичного ООП, чтобы в 99% случаев по тонкому льду не ходить.

Но ты лучше подробнее расскажи о задаче, которая требует столь странных объектов. Это интересно.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от P1XeL

> static_cast<our_dynamically_generated_struct *>(buf)

С аллокаторами можно и *такое* сделать, но для этого надо, чтобы buf был сериализован из проги, и маппинг памяти был на постоянное место. Пример писать не буду.

www_linux_org_ru ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.