LINUX.ORG.RU

Планы по выпуску GTK+ версии 3

 


1

0

В списке рассылки gtk-devel-list обсуждаются планы выпуска GTK+ версии 3. Основные подготовительные действия, которые необходимо предпринять в текущей ветке:

  • Спрятать все открытые поля структур с помощью макроса GSEAL(). В случае необходимости предоставить новые методы доступа к этим полям. Также должны быть скрыты поля-указатели "priv" на структуры, содержащие закрытые данные. Эти действия уже практически полностью проведены в репозитории git://git.imendio.com/projects/gtk+.git
  • Реализовать закрытые члены класса, что включает изменения в коде GType.
  • Объявить как deprecated публичные данные класса с помощью макроса GSEAL().
  • Поскольку не останется простого способа для доступа к полям класса, а использование g_object_[sg]et() утомительно, необходимо ввести новые методы доступа, вроде g_object_get_int(), *double(), *string() и т.д.
  • Существует множество макросов, таких как GTK_WIDGET_GET_FLAGS(), которые всегда были причиной многочисленных проблем (см. bug #69872). Необходимо реализовать нормальные методы доступа (в виде функций) и избавиться от этих макросов.
  • GtkStyle, без сомнений, самый сложный тип, нуждающийся в скрытии публичных полей, и до релиза должно быть проведено множество исследований.
  • Избавиться от всего кода, объявленного deprecated в 2.x. Это подразумевает все соответствующие виджеты и функции.
  • Удалить все поля структур из публичного API. Есть два способа достичь этого:
    a) переместить все структуры в закрытые заголовки;
    b) переместить структуры в C-файл реализации, но тогда всей библиотеке придётся использовать соответствующие методы доступа.
    Эти варианты ещё обсуждаются.
  • Отключить deprecated-код по умолчанию во флагах компиляции.
Таким образом, версия 3.0 будет готова к релизу. Все приложения, которые собираются для ветки 2.x с макросом GSEAL() и не используют deprecated-кода, будут без проблем собираться для ветки 3.x. Наверное, таким образом разработчики пытаются избежать кошмара миграции, который можно видеть на примере библиотеки Qt.

>>> Подробности

★★★★

Проверено: JB ()

Осталось только добавить, что код генерённый даже "гранд" компайлерами просто ужасающ (даже для просто С).

P.S. Постулат С - кроссплатформенный ассемблер - это несусветная чушь...

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

>Если удаляешь руками, то parent по второму разу удалять не будет :)

И это главное ::))

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

Ассемблеры предполагают эквивалентное преобразование код=>маш.инструкция (если не заморачиваться с макросами). Им практически неведомо понятие оптимизации.(За мелкими исключениями дуализма комманд). Код не зависит от версии. В самом синтаксисе С отсутсвуют механизмы для реализации специфических наборов расширений типа MMX,SSE и пр. Язык С изначально был близок к архитектуре PDP-10/11 - но с тех пор много воды утекло 8).

Вобщем "кроссплатформенный ассемблер" - это не более чем поэтическая вольность... Впрочем это чисто моё мнение - хотя я и не одинок в нём 8)

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

> Ассемблеры предполагают эквивалентное преобразование код=>маш.инструкция (если не заморачиваться с макросами). Им практически неведомо понятие оптимизации.

В Си это отображение довольно очевидно. Не однозначно, конечно, но на то он и "кроссплатформенный".

> Впрочем это чисто моё мнение - хотя я и не одинок в нём 8)

Вас таких мало.

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

Ассемблером его зовут не за доступ к железу. А потому что основа любого языка (не только програмиирования)- это построение некоторого нового уровня абстракций. Так вот С над ассемблером очунь уж тонкий уровень абстракции. С это скорее кросплатформенный ассемблер ассемблер с синтаксическим сахором. Функции там - точно как в ассемблере. Массивов нет - есть синстаксический сахар к ассемблерной адресной арифметике. Вон если заценить MASM - так там на макросах сделан удобный доступ к аргументам функций... что то типа циклов - но всё это не даёт принципиально новый уровень абстракции. А потому не совсем тянет на "язык"

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

>>>Вас таких мало.

Это хорошо или плохо ? 8)

А если серьёзно - то очевидность весьма иллюзорна. Иногда просто диву даешся во что вылилась безобидная последовательность. Ну да это вопросы к качеству оптимизации.

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

>>инкапсуляции,

>Её нет, так как надо модифицировать интерфейс (.h файл) при добавлении изменений в private секцию.

pimpl?

>Кроме того, по поводу приватности следует прочитать [Sutter 2005, Item 16]

Я не помню точно (и влом доставать книгу), но там о несанкционированном доступе к private-секции? Если да, то аналогия из серии "имея физический доступ к компьютеру, можно его взломать".

>Решение этой проблемы (фабрики объектов) нетривиально [Alexandrescu 2001, Chapter 8]

Чем не угодила фабрика от "банды 4-х"?

>Наследования в С++ нет, так как в С++ нету мета-объектного протокола.

молчу.

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

> В самом синтаксисе С отсутсвуют механизмы для реализации специфических наборов расширений типа MMX,SSE

но ведь они то и не используется как правило, выключаем оптимизацию, ставим набор инструкций от 386 и получаем "ассемблер"? или я не прав?

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

>>Её нет, так как надо модифицировать интерфейс (.h файл) при добавлении изменений в private секцию

есть d-указатели (но ты о них не знал)

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

кстати насчет MMX, SSE и т.п. - никто не мешает использовать inline функции написанные на asm( если компилятор поддерживает C99 - кстати MS Visual этим не страдает ( тихо в сторону: уроды... ), в результате получаем вполне осмысленный код, с таким же прямым преобразованием код=>маш.инструкция, один раз написать два файла и пользоваться ими( да и наверняка в google code не так сложно найти примеры )

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

>gtk и так полнейший тормоз по сравнению с qt

В свое время единственной причиной, по которой я выбрал Gnome (а потом XFCE) а не KDE, была медленная загрузка и работа последнего, включая большое потребления памяти. Gtk тоже поразил меня своей простотой и изяществом, и после этого я кеды даже не устанавливал.

P.S. Хотя изначально у меня были кеды, и кодил даже в Qt немного.

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

>>>инкапсуляции,

>>Её нет, так как надо модифицировать интерфейс (.h файл) при добавлении изменений в private секцию.

>pimpl?

Костыль.

>>Кроме того, по поводу приватности следует прочитать [Sutter 2005, Item 16]

>Я не помню точно (и влом доставать книгу), но там о несанкционированном доступе к private-секции? Если да, то аналогия из серии "имея физический доступ к компьютеру, можно его взломать".

Там о том что

class Bar {
public:
void foo(double f);
private:
void foo(int f);
};

Bar bar;
bar.foo(21);

Даст ошибку вида "неоднозначная конструкция", т.к приватные методы и данные компилятор рассматривает равноправно с публичными и отвергает в самый последний момент, при проверке прав доступа. В данном случае до проверки доступа компилятор не дойдет и отвалится раньше с "неоднозначной конструкцией".

>>Решение этой проблемы (фабрики объектов) нетривиально [Alexandrescu 2001, Chapter 8]

>Чем не угодила фабрика от "банды 4-х"?

У Александреску специфика С++ проработана лучше. И вообще фабрики малополезны, поскольку Class.forName в С++ нет, так что фабрику конфиг-файлом не инициализируешь. Остается только черезжопная конструкция вида

// inside .cpp file

namespace {
Foo* createFoo() {
return new Foo;
}

class FactoryRegister {
public:
FactoryRegister() {
Factory::Instance().register("foo", &createFoo);
}
};

FactoryRegister reg;
};

Таким макаром код регистрации продуктов останется в файлах с продуктами. Только вот это хреновое решение т.к. фабрика должна инициализироваться из конфига. И глобальные статические объекты запрещены многими стандартами кодирования.

>>Наследования в С++ нет, так как в С++ нету мета-объектного протокола.

>молчу.

Молчи дальше. Без мета-объектного протокола наследования не бывает. Точка.

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

> Вам очевидно, что в деструкторе MyDialog: public QDialog не нужно вызывать delete для MyHighlighter: public QSyntaxHighlighter, но нужно для MyVector: public std::vector<int>? А всё потому, что для QObject применяется своё - не укладывающееся в концепцию C++ - управление памятью в лучших традициях покойного MFC

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

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

> Без мета-объектного протокола наследования не бывает. Точка.

AFAIK, только в CLOS есть MOP. Это значит, что только в CLOS есть наследование?

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

>кстати насчет MMX, SSE и т.п. - никто не мешает использовать inline функции написанные на asm( если компилятор поддерживает C99 - кстати MS Visual этим не страдает ( тихо в сторону: уроды... )

OMG! с каких это пор __asm movd eax,mm0 и т.д. уже отменили? o_0

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

> AFAIK, только в CLOS есть MOP.

Не, не только. Есть везде, где можно работать с определением класса, как с объектом. Но в CLOS, по всей видимости, он наиболее кучерявый.

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

> OMG! с каких это пор __asm movd eax,mm0 и т.д. уже отменили? o_0

OMG, c каких это пор в 32-битный регистр можно скопировать 64-битный? o_0

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

> Без мета-объектного протокола наследования не бывает. Точка.

Почему? Замечание про склеивание быдлоблобов относилось к реализации наследования, а не к самой концепции.

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

>> AFAIK, только в CLOS есть MOP.

>Не, не только. Есть везде, где можно работать с определением класса, как с объектом

"Работать" - это значит, изменять? Что-то я сомневаюсь, что нашего друга устроит read-only доступ.

Под каким именем проходит MOP в Яве? reflection?

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

>OMG, c каких это пор в 32-битный регистр можно скопировать 64-битный? o_0

просвящаться - в гугл

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

>OMG, c каких это пор в 32-битный регистр можно скопировать 64-битный? o_0

а когда было нельзя?

>Инструкция MOVD пересылает 32 младших бита регистра ММХ в регистр общего назначения или память Или же из регистра общего назначения/памяти в регистр ММХ В последнем случае, кроме собственно пересылки, биты 32-64 соответствующего регистра обнуляются

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

> поскольку Class.forName в С++ нет, так что фабрику конфиг-файлом не инициализируешь. Остается только черезжопная конструкция вида

4.2, а про RTTI вы слышали?

в wxWidgets к примеру это делается так:

wxObject * wxCreateDynamicObject(const wxString& className)

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

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

> "Работать" - это значит, изменять? Что-то я сомневаюсь, что нашего друга устроит read-only доступ.

Ну твой друг вообще отдельный разговор, но почему бы и не быть работе read-only? Если специфика языка такова, что вся мета-активность позволяется исключительно в compile-time, то r/w и не получится.

> Под каким именем проходит MOP в Яве? reflection?

Это одно из свойств MOP. Вообще говоря, The Art Of Metaobject Protocol весьма познавательная книжка. Хотя бы вводную часть полезно для расширения кругозора прочитать (и где-то на просторах интернета можно скачать).

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

>>Как как насчет доказательств отсуствия инкапсуляции, полиморфизма, наследования в Си++?

>[Absurd @ LOR]

абсурд

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

Довольно забавно =) По всей видимости, доказать отсутствие инкапсуляции, полиморфизма и наследования в C++ он смог только себе =)

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

> а когда было нельзя?

Ну да, что это я?...

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

дело не в том, я имел ввиду что так можно "спрятать" ассемблер в основном коде

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

> почему бы и не быть работе read-only?

Да по мне, MOP вобще не является необходимым для наличия наследования. Но если "встроенная" модель наследования чем-то не устраивает, r/o MOP - это всё равно, что никакого MOP, поскольку ничего не исправишь.

> The Art Of Metaobject Protocol весьма познавательная книжка.

Она о CLOS?

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

>>Даст ошибку вида "неоднозначная конструкция", т.к приватные методы
 и данные компилятор рассматривает равноправно с публичными и 
отвергает в самый последний момент, при проверке прав доступа. В 
данном случае до проверки доступа компилятор не дойдет и отвалится 
раньше с "неоднозначной конструкцией".

Вижуал ?

Потому что gcc-4.1 говорит

vec.cpp: In function ‘int main(int, char**)’:
vec.cpp:7: error: ‘void Bar::foo(int)’ is private
vec.cpp:13: error: within this context

$ cat vec.cpp

class Bar
{
 public:
     void foo(double f);
 private:
     void foo(int f);
};

int main(int, char**)
{
    Bar b;
    b.foo(21);

    return 0;
}

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

В рубях он вроде как не read-only. Классы можно хачить на ходу. И даже отдельные объекты классов.

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

> Да по мне, MOP вобще не является необходимым для наличия наследования. Но если "встроенная" модель наследования чем-то не устраивает, r/o MOP - это всё равно, что никакого MOP, поскольку ничего не исправишь.

Строго говоря, MOP (манипуляция с определениями классов) обязана быть в любом ОО языке. И в C++ MOP тоже есть, потому что есть классы, есть наследование, есть виртуальные функции, есть темплейты, генерящие специализации шаблонных классов. Чтобы всё это было, нужен MOP. В C++ MOP существует, в основном, на стадии компиляции, но всё же он есть. RTTI к MOP тоже причисляется, но это весьма хиленькая фича. А вот если разродятся на множественную диспетчеризацию, то будет уже нормальная MOPовская фича в рантайме.

> Она о CLOS?

Она о MOP на примере CLOS. Сами авторы пишут в введении, что прочесть книжку будет полезно и тем, кто хочет в другой язык добавить MOP. Или понять, как вообще такие вещи организуются, и что в них должно быть. Я сам читать AMOP начал, потом подзабросил что-то, но книжка написана довольно простым языком и читается легко.

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

> про RTTI вы слышали?

При включении RTTI struct/class перестает быть двоично совместимым с С, даже если нет виртуальных методов. Да и очень чахл API этого rtti....

> wxObject * wxCreateDynamicObject(const wxString& className)

А как это реализовано, интересно? В двух словах...

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

> рубях он вроде как не read-only. Классы можно хачить на ходу

В Питоне - точно не r/o, наверное, это характерно для динамических или интерпретируемых языков. Поэтому я и спрашиваю - как с этим в Яве, она же хотя бы статически компилируемая.

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

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

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

Статическая компиляция режет много возможностей MOP. Лучше всего для MOP подходит Лисп из-за своего принципа "программа есть данные, данные есть программа" и наличия eval в рантайме.

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

> Конечно, это не то, что требуется.

Я читал, что для поддержки аспектов санкам пришлось вносить изменения в VM и генерацию байткода (а вот в Лиспе AspectL - обычная библиотека ;)

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

> Лисп из-за своего принципа "программа есть данные, данные есть программа" и наличия eval в рантайме.

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

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

В CL тоже новый lexenv создаётся.

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

> Я бы сказал, до нуля 8)

Во время компиляции MOP всё равно есть и работает.

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

> Да и очень чахл API этого rtti....
чего не хватает? кстати недостающее можно реализвать и самому

> А как это реализовано, интересно? В двух словах...

два макроса - один в .h, один в .cpp

DECLARE_DYNAMIC_CLASS( myClass ) и 
IMPLEMENT_DYNAMIC_CLASS( myClass, MyClassParent )

вт собс-но и все, вот как это внутри:

первое разворачивается в:

#define DECLARE_ABSTRACT_CLASS(name)                                          \
    public:                                                                   \
        static wxClassInfo ms_classInfo;                                      \
        virtual wxClassInfo *GetClassInfo() const;

второе разворачивается в 

// common part of the macros below
#define wxIMPLEMENT_CLASS_COMMON(name, basename, baseclsinfo2, func)          \
    wxClassInfo name::ms_classInfo(wxT(#name),                                \
            &basename::ms_classInfo,                                          \
            baseclsinfo2,                                                     \
            (int) sizeof(name),                                               \
            (wxObjectConstructorFn) func);                                    \
                                                                              \
    wxClassInfo *name::GetClassInfo() const                                   \
        { return &name::ms_classInfo; }





class WXDLLIMPEXP_BASE wxClassInfo
{
public:
    wxClassInfo( const wxChar *className,
                 const wxClassInfo *baseInfo1,
                 const wxClassInfo *baseInfo2,
                 int size,
                 wxObjectConstructorFn ctor )
        : m_className(className)
        , m_objectSize(size)
        , m_objectConstructor(ctor)
        , m_baseInfo1(baseInfo1)
        , m_baseInfo2(baseInfo2)
        , m_next(sm_first)
        {
            sm_first = this;
            Register();
        }

    ~wxClassInfo();

    wxObject *CreateObject() const
        { return m_objectConstructor ? (*m_objectConstructor)() : 0; }
    bool IsDynamic() const { return (NULL != m_objectConstructor); }

    const wxChar       *GetClassName() const { return m_className; }
    const wxChar       *GetBaseClassName1() const
        { return m_baseInfo1 ? m_baseInfo1->GetClassName() : NULL; }
    const wxChar       *GetBaseClassName2() const
        { return m_baseInfo2 ? m_baseInfo2->GetClassName() : NULL; }
    const wxClassInfo  *GetBaseClass1() const { return m_baseInfo1; }
    const wxClassInfo  *GetBaseClass2() const { return m_baseInfo2; }
    int                 GetSize() const { return m_objectSize; }

    wxObjectConstructorFn      GetConstructor() const
        { return m_objectConstructor; }
    static const wxClassInfo  *GetFirst() { return sm_first; }
    const wxClassInfo         *GetNext() const { return m_next; }
    static wxClassInfo        *FindClass(const wxChar *className);

        // Climb upwards through inheritance hierarchy.
        // Dual inheritance is catered for.

    bool IsKindOf(const wxClassInfo *info) const
    {
        return info != 0 &&
               ( info == this ||
                 ( m_baseInfo1 && m_baseInfo1->IsKindOf(info) ) ||
                 ( m_baseInfo2 && m_baseInfo2->IsKindOf(info) ) );
    }

#if WXWIN_COMPATIBILITY_2_4
    // Initializes parent pointers and hash table for fast searching.
    wxDEPRECATED( static void InitializeClasses() );
    // Cleans up hash table used for fast searching.
    wxDEPRECATED( static void CleanUpClasses() );
#endif

public:
    const wxChar            *m_className;
    int                      m_objectSize;
    wxObjectConstructorFn    m_objectConstructor;

        // Pointers to base wxClassInfos: set in InitializeClasses

    const wxClassInfo       *m_baseInfo1;
    const wxClassInfo       *m_baseInfo2;

        // class info object live in a linked list:
        // pointers to its head and the next element in it

    static wxClassInfo      *sm_first;
    wxClassInfo             *m_next;

    // FIXME: this should be private (currently used directly by way too
    //        many clients)
    static wxHashTable      *sm_classTable;

private:
    // InitializeClasses() helper
    static wxClassInfo *GetBaseByName(const wxChar *name);

    DECLARE_NO_COPY_CLASS(wxClassInfo)

protected:
    // registers the class
    void Register();
    void Unregister();
};

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

А, ну понятно. Закат солнца вручную. В принципе, все это можно делать и на С. Но к плюсам как ОО языку это уже никакого отношения не имеет.

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

> А, ну понятно. Закат солнца вручную.

"Под капотом" Явы и прочих происходит то же самое... Только там весь этот мусор вставляется компилятором, и нет возможности от него отказаться :)

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

У меня нет вопросов к этому решению. У меня к вопросы к языку, имеющему наглость называть себя ОО.

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

В ОО языках это именно так "надо или нет - оно будет использоваться". На то они и ОО. Вот в С ОО на уровне языка нет - так вот там все вручную. Надо - используете (gobject), не надо - не используете. А когда ОО "как бы" (кагбэ?) есть, но приходится городить огороды для более-менее приличных вещей...

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