Russian Qt Forum
Ноябрь 23, 2024, 15:53 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Глобальные переменные в чужом API  (Прочитано 2451 раз)
kramer
Гость
« : Декабрь 24, 2012, 12:47 »

Здравствуйте, друзья!

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

Код:
extern "C" StructIntType StructInt27 = {
    0, // Default value
    0, // Min Value
    100, // Max Value
    FLAGS_NONE, // Flags
    NULL // Callback pointer
};

Сами структуры StructIntType и прочие определены в заголовочном файле - по одной на каждый тип контрола. Имя глобальной переменной при этом строго фиксировано, Int в имени позволяет хост-приложению определить тип моего контрола, а 27 - его место в сетке на форме (нет, это не я придумал, из-звините). Соответственно, в коде этот контрол используется по этому имени а-ля StructInt27.Value = SomeValue;. Не очень удобно, не правда ли?

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

ОС - Линукс, компилятор - gcc/g++ 3.4.

Спасибо.
Записан
ssoft
Гость
« Ответ #1 : Декабрь 24, 2012, 15:25 »

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

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

Код:

#define INT_CTRL( MyCtrlName, FormNumber, Default, Min, Max ) \
extern "C" StructIntType StructInt27 = { \
    Default, \
    Min, \
    Max, \
    FLAGS_NONE, \
    NULL \
}; \
StructIntType & MyCtrlName = StructInt27 ; \

Записан
kramer
Гость
« Ответ #2 : Декабрь 24, 2012, 16:31 »

А не используется ли вдобавок ко всему описанному какие-нибудь шаги предкомпиляции.
Другими словами, какой механизм обработки номера места в сетке на форме?
Спасибо за ответ. Все гораздо проще, чем вы думаете, хост-приложение просто смотрит на все экспортируемые символы моего DSO, и, если находит символ, подходящий по шаблону вида Struct{Int|Float|etc}{0..121}, то считает, что это контрол соответствующего типа в соответствующей ячейке сетки на форме.

Ваш подход первым приходит в голову, но есть закавыка - поскольку присутствует инициализатор, компилятор будет считать, что это определение символа, и соответственно при включении в несколько исходных файлов возникнет конфликт глобальных имен. Я выкрутился пока так: в отдельном заголовочном файле ControlMacros.h я определяю каждый такой макрос в зависимости от условия #ifdef __CONTROL_UNIT. В первом случае он буквально совпадает с вашим (только позиция вынесена в аргумент, и нет последней строчки), а во втором - как раз объявление этой структуры как extern и указателя по имени MyCtrlName (в моем случае, функции) на нее. Затем, скажем, в еще одном заголовочном файле Controls.h я с помощью этого условного макроса определяю все контролы, которые мне понадобятся, и наконец при включении Controls.h в один из исходных файлов, например, Controls.cpp, я ПЕРЕД включением определяю __CONTROL_UNIT, и вуаля - в этом и только в этом файле определяются экспортируемые символы, а во всех остальных, куда включается Controls.h - только их декларации и ссылки/функции с осмысленными именами. Вот такой вот изврат, может кому пригодится.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.045 секунд. Запросов: 21.