С++: метаданные своими руками
От: Андрей Мартынов Россия  
Дата: 25.11.03 16:19
Оценка: 1785 (36) -1
Статья:
С++: метаданные своими руками
Автор(ы): Андрей Мартынов
Дата: 30.11.2003
В статье рассмотрен декларативный подход к решению задачи чтения/записи XML-файлов из программ на классическом C++. Метод основан на построении специальной структуры статических данных — метаданных типов.


Авторы:
Андрей Мартынов

Аннотация:
В статье рассмотрен декларативный подход к решению задачи чтения/записи XML-файлов из программ на классическом C++. Метод основан на построении специальной структуры статических данных – метаданных типов.
Re: С++: метаданные своими руками
От: dad  
Дата: 27.11.03 14:19
Оценка: :)
АМ>Статья:

почему статья без текста?
(это как номер неоплаченной мобилы )

censored -- ПК.
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Re[2]: С++: метаданные своими руками
От: Sergeem Израиль  
Дата: 27.11.03 16:20
Оценка:
Здравствуйте, dad, Вы писали:

АМ>>Статья:


dad>почему статья без текста?

dad>(это как номер неоплаченной мобилы )

sorry за offtopic.
это они так журнал продвигают, чтоб его покупали.
я не гордый, подожду пол-года.
Serge.

Hасколько проще была бы жизнь, если бы она была в исходниках.
Re[3]: С++: метаданные своими руками
От: Зверёк Харьковский  
Дата: 27.11.03 17:00
Оценка: +1 :))
Здравствуйте, Sergeem, Вы писали:

S>это они так журнал продвигают, чтоб его покупали.

S>я не гордый, подожду пол-года.

[опять же OFF]
(с чувством глубокого морального удовлетворения): — Пусть, пусть эти придурки выделываются, кропают свои статьишки, выпускают свои журнальчики! Мы, русские люди, кушаем только бесплатное!

так, что ль?
FAQ — це мiй ай-кью!
Re[3]: С++: метаданные своими руками
От: Рома Мик Россия http://romamik.com
Дата: 27.11.03 21:37
Оценка:
Здравствуйте, Sergeem, Вы писали:

S>это они так журнал продвигают, чтоб его покупали.

S>я не гордый, подожду пол-года.
Разве полгода? А мне казалось быстрее. Я, кстати, rsdn magazine ни разу не покупал, так как ни разу не видел в продаже, а заказывать... мне как-то неловко, чтобы из-за меня человек в лютую непогоду по улице бегал, такое вот у меня небуржуйское воспитание... ( эй, я никого не осуждаю, спрячьте свои шотганы )
А не в непогоду как глупо заказывать, человек с удовольствием прогуляется по свежему воздуху, а ему деньги за это плати...
... << RSDN@Home 1.1.0 stable >>
Re[4]: С++: метаданные своими руками
От: dad  
Дата: 01.12.03 11:29
Оценка:
РМ>Разве полгода? А мне казалось быстрее. Я, кстати, rsdn magazine ни разу не покупал, так как ни разу не видел в продаже, а заказывать... мне как-то неловко, чтобы из-за меня человек в лютую непогоду по улице бегал,

это где так? (или шутишь?)
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Re[3]: С++: метаданные своими руками
От: Yess  
Дата: 03.12.03 03:22
Оценка:
Здравствуйте, Sergeem, Вы писали:

S>sorry за offtopic.

S>это они так журнал продвигают, чтоб его покупали.
S>я не гордый, подожду пол-года.

А мне эта статья по почте пришла недели две назад — рассылка RSDN
Re: С++: метаданные своими руками
От: Shire  
Дата: 05.12.03 08:20
Оценка:
Подобное решение есть у Константина Книжника в движках объектно-ориентированных баз данных.
Re[2]: С++: метаданные своими руками
От: PM  
Дата: 05.12.03 12:18
Оценка:
Здраствуйте, Shire. Вы писали:

S> Подобное решение есть у Константина Книжника

Давненько я на его сайт не заглядывал, но насколько мне помнится, Книжник реализовал reflection на основе run-time классов (наподобие MFCшного CRuntimeClass). Подход же описанный в статье, основан на шаблонах. Первый раз такое решение я увидел в XTL
Posted via RSDN NNTP Server 1.7 "Bedlam"
Re: VC++6.0 Проблема
От: romashka Удмуртия  
Дата: 16.01.04 09:01
Оценка:
Здравствуйте, Андрей Мартынов
АМ>В статье рассмотрен декларативный подход к решению задачи чтения/записи XML-файлов из программ на классическом C++. Метод основан на построении специальной структуры статических данных – метаданных типов.

Не удалось собрать под VC++ 6.0.
Ошибка:
error C2629: unexpected 'struct Rsdn::Serializer::FieldAttrubutes::StructFieldAttrubute<StructType,StructFieldType> ('

В строке:

>> StructFieldAttrubute( FieldName name

, StructFieldType StructType::* offset
, const StructFieldType* pDefault = NULL
, const Layout<StructFieldType>& layout = DefaultLayout<StructFieldType>()
)
: m_layout(layout)
, m_name(name)
, m_offset(offset)
, m_pDefault(pDefault)
{}


В статье не сказано об ограничения для платформы.
В силу ограничений могу использовать только VC 6.0, а данное решение мне очень кстати.
Re: С++: метаданные своими руками
От: nobody2 Россия  
Дата: 17.02.04 07:35
Оценка:
Здравствуйте, Андрей Мартынов, Вы писали:

АМ>Статья:



АМ>Авторы:

АМ> Андрей Мартынов

АМ>Аннотация:

АМ>В статье рассмотрен декларативный подход к решению задачи чтения/записи XML-файлов из программ на классическом C++. Метод основан на построении специальной структуры статических данных – метаданных типов.

где объявлены и для чего используются
CT2A()
CW2T()
Re[2]: С++: метаданные своими руками
От: folk Россия  
Дата: 18.02.04 01:20
Оценка:
Здравствуйте, nobody2, Вы писали:

N>Здравствуйте, Андрей Мартынов, Вы писали:


АМ>>Статья:



АМ>>Авторы:

АМ>> Андрей Мартынов

АМ>>Аннотация:

АМ>>В статье рассмотрен декларативный подход к решению задачи чтения/записи XML-файлов из программ на классическом C++. Метод основан на построении специальной структуры статических данных – метаданных типов.

N>где объявлены и для чего используются

N>CT2A()
N>CW2T()

Это макросы преобразования строк в ATL, сокращения от ConstTchar2Ansi и ConstWide2Tchar.
Смотри в MSDN T2A и W2T
На самом деле, люди не читают газеты, они принимают их каждое утро, так же как ванну. ©Маршалл Мак-Льюэн
Re[2]: VC++6.0 Проблема
От: Salex100 Россия  
Дата: 02.03.04 14:22
Оценка:
Здравствуйте, romashka, Вы писали:

R>Здравствуйте, Андрей Мартынов

АМ>>В статье рассмотрен декларативный подход к решению задачи чтения/записи XML-файлов из программ на классическом C++. Метод основан на построении специальной структуры статических данных – метаданных типов.

R>Не удалось собрать под VC++ 6.0.

R>Ошибка:
R> error C2629: unexpected 'struct Rsdn::Serializer::FieldAttrubutes::StructFieldAttrubute<StructType,StructFieldType> ('

R>В строке:


>>> StructFieldAttrubute( FieldName name

R> , StructFieldType StructType::* offset
R> , const StructFieldType* pDefault = NULL
R> , const Layout<StructFieldType>& layout = DefaultLayout<StructFieldType>()
R> )
R> : m_layout(layout)
R> , m_name(name)
R> , m_offset(offset)
R> , m_pDefault(pDefault)
R> {}


R>В статье не сказано об ограничения для платформы.

R>В силу ограничений могу использовать только VC 6.0, а данное решение мне очень кстати.

Те же грабли и с VC 7.0. Проблема в использовании в качестве дефолтного значения шаблонной функции.
Жизнь удалась!
Re: С++: метаданные своими руками
От: nobody2 Россия  
Дата: 02.03.04 14:56
Оценка:
Здравствуйте, Андрей Мартынов, Вы писали:

АМ>Статья:

АМ>...

В статье приведен пример чтения вектора из XML-файла:
...
std::vector<int> vec;
Xml::Load(_T("vec.xml"),  _T("vec"), &vec);
...

Не понятно следующее: при вызове функции xml::Load()
template <typename DataType>
void Load( const tstring&            pathFile
         , const tstring&            rootTag
         , DataType*                 pData
         , const MetaClass<DataType>& metaData = DefaultMetaClass<DataType>()
         )
{...}

ей в качестве последнего параметра передается объект, создаваемый ф-ей DefaultMetaClass<std::vector<int> >()
template <typename Data>
const MetaClass<Data>& DefaultMetaClass()
{
    static StructClassMeta<Data> g_metaData(DefaultLayout<Data>());
    return g_metaData;
}

которая, в свою очередь, возвращает объект StructClassMeta<std::vector<int> >, который при создании инициализируется объектом, создаваемым функцией DefaultLayout<std::vector<int> >()
template <typename DataType>
const Layout<DataType>& DefaultLayout()
{
    static DataType::LayoutDefault g_layout;
    return g_layout;
}

которая возвращает объект std::vector<int>::LayoutDefault;

вопрос: кто определил std::vector<int>::LayoutDefault?
Re[2]: С++: метаданные своими руками
От: nobody2 Россия  
Дата: 03.03.04 10:05
Оценка:
Вопрос закрыт.
В SerializerPrim.h присутствует специализация DefaultMetaClass для примитивов и векторов.

Поиск ответа занял целые сутки, однако.
ИМХО, организация кода и названия классов оставляют желать лучшего.
Re: С++: метаданные своими руками
От: Libra Россия  
Дата: 03.03.04 15:00
Оценка:
Здравствуйте, Андрей Мартынов, Вы писали:

АМ>Статья:



АМ>Авторы:

АМ> Андрей Мартынов

АМ>Аннотация:

АМ>В статье рассмотрен декларативный подход к решению задачи чтения/записи XML-файлов из программ на классическом C++. Метод основан на построении специальной структуры статических данных – метаданных типов.

Можете запинать меня ногами, мне понравилось... И дело не в названиях классов или еще в чем-либо, а в самом решении. Тем более это open source, дорабатывай сколько влезет, если это необходимо.
Species come and go, but the earth stands forever fast...
Re: С++: метаданные своими руками
От: Salex100 Россия  
Дата: 04.03.04 14:34
Оценка:
Здравствуйте, Андрей Мартынов, Вы писали:

Попытался рикрутить к WTL контролу (диалоговое окно). После загрузки конфигурации приложение с грохотом падает.

Хотя с моими классами работает!
Жизнь удалась!
Re[2]: С++: метаданные своими руками
От: Salex100 Россия  
Дата: 05.03.04 09:13
Оценка:
Здравствуйте, Salex100, Вы писали:

S>Здравствуйте, Андрей Мартынов, Вы писали:


S>Попытался рикрутить к WTL контролу (диалоговое окно). После загрузки конфигурации приложение с грохотом падает.


S>Хотя с моими классами работает!


Причина найдена. В функции Load есть следуящая строчка:
  *pData = metaData.ReadNode(NodeImpl(pRootElement));


Что приводит к вызову следуюшего метода из StructClassMeta
    StructType ReadNode(const INode& node) const 
    {
        StructType data;
        for_each(m_layout.begin(), m_layout.end()
            , ReadField(node, &data));
        return data;
    }
Жизнь удалась!
Re: на вопрос не ответили
От: AGo Россия  
Дата: 24.03.04 03:49
Оценка:
Тут я вижу бы ли заданы вопросы оставленные без ответа
касательно ошибок при переносе кода на VC версиями ниже 8.0
error C2629: unexpected 'Rsdn::Serializer::FieldAttrubutes::StructFieldAttrubute<StructType,StructFieldType> ('
error C2334: unexpected token(s) preceding '{'; skipping apparent function body
error C2664: 'Rsdn::Serializer::MetaClasses::StructClassMeta<struct Clr>::__ctor' : cannot convert parameter 1 from 'Clr_Layout3'

хотелось бы все таки знать, как убрать эти ошибки
спасибо.
Re[2]: С++: метаданные своими руками
От: adontz Грузия http://adontz.wordpress.com/
Дата: 24.03.04 04:02
Оценка:
Здравствуйте, Libra, Вы писали:

L>Можете запинать меня ногами, мне понравилось... И дело не в названиях классов или еще в чем-либо, а в самом решении. Тем более это open source, дорабатывай сколько влезет, если это необходимо.


Да, нет понимаешь, идея какая-то промежуточная. Потому что если храним всё в CRuntimeClass требуем наследования от него и проч., то тогда надо использовать RTTI и не придумывать свои LayoutDefault. Если же используем шаблоны, то вся информация наобходимая для сериализации может быть получена ещё на этапе компиляции за счёт 1000 и 1 раз перегруженных функций и опять не нужен LayoutDefault. А то что мы имеет это дублирование RTTI. Нет, как продукт очень даже ничего, но как идея лично мне не нравится, хотя не буду отрицать полезность таких идей и не буду отричать, что то чем я сейчас пользуюсь было написано в том числе и после прочтения этой статьи.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re: С++: метаданные своими руками
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 22.04.04 16:13
Оценка:
Здравствуйте, Андрей Мартынов, Вы писали:

АМ>В статье рассмотрен декларативный подход к решению задачи чтения/записи XML-файлов из программ на классическом C++. Метод основан на построении специальной структуры статических данных – метаданных типов.


а чего надо подкрутить, чтоб можно было с полями типа CString работать, типа так:

struct Clr
{
  CString str;

  struct LayoutDefault : public Layout<Clr>
  {
    LayoutDefault()
    {  //        тег         поле        значение по умолчанию
      Simple(_T("STRING"  ), &Clr::str, "default string");
    }
  };
};
Re[2]: С++: метаданные своими руками
От: Andis  
Дата: 09.03.05 05:55
Оценка:
А как решается вопрос с наследованием структур?

например:


struct a
{
   int i;
   int j;
   struct LayoutDefault : public Layout<Clr>
   {
    LayoutDefault()
    {  //        тег         поле        значение по умолчанию
      Simple(_T("VarI"  ), &a::i, 10);
      Simple(_T("VarJ"  ), &a::j, 10);
    }
  };

}

struct b : public a
{
   int x;
   int y;

  ????????????????

}
Re: Утечки памяти
От: Macedonian Россия  
Дата: 19.05.05 03:31
Оценка:
При сборке обнаружились утечки памяти в нескольких местах, кто-нибудь это уже исправлял?
Re[2]: Утечки памяти
От: CiViLiS Россия  
Дата: 21.05.05 06:10
Оценка:
Здравствуйте, Macedonian, Вы писали:

M>При сборке обнаружились утечки памяти в нескольких местах, кто-нибудь это уже исправлял?

Я много чего уже исправил в этом коде, правда утечек не помню. Так что пример кода вызывающий утечку в студию, а там посмотрим.

Последний баг который я нашел, это проблема с ексепшенами:
struct Exception : public std::exception
{
    Exception(const tstring& a_msg) : msg(a_msg) {}
    const char *what() const
        { return CT2A(msg.c_str());    } // what вернет указатель на временный объект, который уже будет удален к моменту выхода из функции
protected:
    const tstring& msg;
};



Фиксил так:
struct Exception : public std::runtime_error
{
    Exception(const tstring& a_msg) 
        : std::runtime_error(std::string(CT2A(a_msg.c_str())))
{}


ЗЫ Могу поделиться всеми своими фиксами, но только в понедельник.
... << RSDN@Home 1.1.4 beta 7 rev. 457>>
"Бог не терпит голой сингулярности" -- Роджер Пенроуз
Re[3]: Утечки памяти
От: Macedonian Россия  
Дата: 31.05.05 14:49
Оценка:
Здравствуйте, CiViLiS, Вы писали:

M>>При сборке обнаружились утечки памяти в нескольких местах, кто-нибудь это уже исправлял?

CVL>Я много чего уже исправил в этом коде, правда утечек не помню. Так что пример кода вызывающий утечку в студию, а там посмотрим.

Извини, что долго не отвечал, сессия )-:
Утечку вызывает код парсинга Xml, помещенный в MFC DLL, причем в консольном приложении тот же код не вызывает у компилятора подозрений в утечке
Собственно, код:
// XmlParserDll.h
//

#include <map>
#include <string>
#include <tchar.h>

#ifdef _UNICODE
    typedef wchar_t             tchar;
    typedef std::wstring        tstring;
    #define tcout               std::wcout
#else
    typedef char                tchar;
    typedef std::string         tstring;
    #define tcout               std::cout
#endif

#define Dll __declspec(dllexport)

class Dll XmlConf
{
public:
    typedef std::map<tstring, tstring> Values;

    XmlConf(const tstring& path);

    char *GetValue(const char *key, const char *def = "");

protected:
    Values m_values;
};

// XmlParserDll.cpp
//

#include "stdafx.h"
#include "XmlParserDll.h"

#include "SerializerXml.h"
#include "SerializerRegistry.h"

using namespace std;
using namespace Rsdn;
using namespace Serializer;
using namespace Tree;

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

struct Pair
{
    tstring key, value;

    struct LayoutDefault : public Layout<Pair>
    {
        LayoutDefault()
        {
            AttributeM(_T("key"  ), &Pair::key  );
            AttributeM(_T("value"), &Pair::value);
        }
    };
};

struct File
{
    typedef std::vector<Pair> Pairs;
    std::vector<Pair> pairs;

    struct LayoutDefault : public Layout<File>
    {
        LayoutDefault()
        {
            Array(_T("appSettings" ), &File::pairs, _T("add" ));
        }
    };
};

struct AppSettings
{
    typedef std::map<tstring, tstring> Values;

    AppSettings(){}
    AppSettings(const tstring& path)
    {
        ::CoInitialize(NULL);
        Load(path);
        ::CoUninitialize();
    }

    void Load(const tstring& path)
    {
        File file;
        Xml::Load(path, _T("configuration"), &file);
        for_each(file.pairs.begin(), file.pairs.end()
            , std::bind1st(std::mem_fun1<void, AppSettings, Pair>(Add)
                , this));
    }

    tstring GetValue(const tstring& key, const tstring& def = _T("")) const
    {
        Values::const_iterator iter = m_values.find(key);
        return iter == m_values.end() ? def : iter->second;
    }

    void Add(Pair pair)
    {
        m_values.insert(Values::value_type(pair.key, pair.value));
    }

    Values GetValues()
    {
        return m_values;
    }

protected:
    Values m_values;
};

char *SysStrDup(const char *pszString)
{
    int iStrLength = strlen(pszString);

    char *pszBuffer = (char *) malloc(iStrLength + 1);

    if (pszBuffer != NULL)
        strcpy(pszBuffer, pszString);

    return (pszBuffer);
}

XmlConf::XmlConf(const tstring& path)
{
    AppSettings conf(path);
    m_values = conf.GetValues();
}

char *XmlConf::GetValue(const char *key, const char *def)
{
    Values::const_iterator iter = m_values.find(key);
    return iter == m_values.end() ? (def != NULL ? SysStrDup(def) : NULL) : SysStrDup(iter->second.c_str());
}


CVL>ЗЫ Могу поделиться всеми своими фиксами, но только в понедельник.

Было бы очень кстати
Re[4]: Утечки памяти
От: CiViLiS Россия  
Дата: 01.06.05 12:49
Оценка:
Здравствуйте, Macedonian, Вы писали:

M>Здравствуйте, CiViLiS, Вы писали:


M>>>При сборке обнаружились утечки памяти в нескольких местах, кто-нибудь это уже исправлял?

CVL>>Я много чего уже исправил в этом коде, правда утечек не помню. Так что пример кода вызывающий утечку в студию, а там посмотрим.

M>Извини, что долго не отвечал, сессия )-:

А я уже как год забыл про это страшное слово

M>Утечку вызывает код парсинга Xml, помещенный в MFC DLL, причем в консольном приложении тот же код не вызывает у компилятора подозрений в утечке

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

Если не работает код который в ДЛЛ, то распространенная проблема, это неправильные (не индентичные) ключи у компилятора/линкера для екзешника и для ДЛЛ. Если про эту проблему не знаешь, то можешь поискать на форуме --- подключение разных CRT часто встречается.

CVL>>ЗЫ Могу поделиться всеми своими фиксами, но только в понедельник.

M>Было бы очень кстати
здесь. Я немного изменил работу со строками, добавил поддержку const_string'ов и ввел новый инт, чтобы была возможность серелизовать в хексе. Исправил работу с enum и еще что-то по мелочи... Подробности не помню -- давно уже правил...
... << RSDN@Home 1.1.4 beta 7 rev. 458>>
"Бог не терпит голой сингулярности" -- Роджер Пенроуз
Re[2]: С++: метаданные своими руками
От: cpp_best  
Дата: 18.02.06 20:14
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>Здравствуйте, Андрей Мартынов, Вы писали:


АМ>>В статье рассмотрен декларативный подход к решению задачи чтения/записи XML-файлов из программ на классическом C++. Метод основан на построении специальной структуры статических данных – метаданных типов.


OE>а чего надо подкрутить, чтоб можно было с полями типа CString работать, типа так:


OE>
OE>struct Clr
OE>{
OE>  CString str;

OE>  struct LayoutDefault : public Layout<Clr>
OE>  {
OE>    LayoutDefault()
OE>    {  //        тег         поле        значение по умолчанию
OE>      Simple(_T("STRING"  ), &Clr::str, "default string");
OE>    }
OE>  };
OE>};
OE>


Внимательно читаем статью к библиотеке, или читаем ошибку при смене типа переменной на CString и получаем:
в файле SerizlizerPrim.h в пространстве имен Rsdn::Serializer::Primitives добавляем шаблон для нужного типа.
Но по-моему тех, что реализованы в библиотеке достаточно. Для строк можно использовать tstring (это typedef на std::wstring), который оперирует 2х байтовыми символами. В значении по умолчанию пишем что-то вроде этого:
std::wstring(L"Microsoft")

С уважением, cpp_best.
P.S. Сам мучился с этим, и как всегда сработала извечная истина: находишь решение в ... (блин, уже спать пора)
Re: как сериализовать контейнер контейнеров контейнеров.
От: WareZzhKa  
Дата: 10.08.06 12:24
Оценка:
Как сериализовать контейнер контейнеров контейнеров...?
Например, вот с этим — std::vector<std::vector<int> > m_v; // всё ок

а вот этот std::vector<std::vector< std::vector<int> > > m_v; //- уже не компилиться
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.