Возникла проблема при использовании глобальных объектов.
В Static Library есть некоторые количество глобальных объектов. Эти объекты являются "creator-ми" других объектов используемых через интерфейсы, иными словами глобальный объект отвечает за создание определенного экземпляра класса и добавляет его вместе с ключом в фабрику классов. На этом работа этих глобальных объектов заканчивается и только при уничтожении они удаляют класс, за который они отвечают, из фабрики классов.
Эта Static Library подключается к MFC приложению. Проблема в том, что при запуске приложения эти глобальные объекты не создаются. Предполагаю, что это связано из-за «неиспользования» этих объектов в приложении или из-за «неиспользования» той единицы трансляции, в которой они объявлены.… Потому, что если в том же файле, где определен глобальный объект, определить любой другой глобальный объект и обратиться к нему в MFC приложении, то все глобальные объекты этого cpp файла, в таком случаи будут созданы. Но такой вариант меня не устраивает.
Здравствуйте, vkoval, Вы писали:
V>Знает ли кто способы решения этой проблемы?
Экспортируй что-нибудь из единицы трансляции, в которой определены эти объекты...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, vkoval, Вы писали:
V>>Знает ли кто способы решения этой проблемы?
E>Экспортируй что-нибудь из единицы трансляции, в которой определены эти объекты...
В таком случаи все работает. Но не хочется из каждого файла что-то экспортировать, притом таких файлом не мало.
Надеялся, что есть более простой способ.
Кстати, с dll тоже работает, но нужна именно статическая библиотека.
И поищи по ключевым словам: "static initializer", "Schwarz counter".
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
. Жаль, поиск на RSDN сейчас не работает.
ГВ>И поищи по ключевым словам: "static initializer", "Schwarz counter".
Почитал... Но там решается проблема порядка создания глобальных объектов, а у меня проблема в том, что в определенной ситуации объекты вообще НЕ создаются!
Здравствуйте, vkoval, Вы писали:
V>В таком случаи все работает. Но не хочется из каждого файла что-то экспортировать, притом таких файлом не мало. V>Надеялся, что есть более простой способ. V>Кстати, с dll тоже работает, но нужна именно статическая библиотека.
Ты ставишь противоречивую задачу: если объект нигде не используется, то компилятор и не будет его создавать. Поэтому нужно либо явно использовать объект, либо как-то обмануть компилятор, тем же экспортом.
Кстати, вообще говоря, не очень удачная затея — добавлять что-то в фабрику на этапе инициализации статических данных. Сразу получаешь сложности с порядком инициализации. Намного надёжнее плюнуть на небольшой оверхед ручной работы и завести простой и примитивный цикл инициализации, вызываемый, например, из InitInstance.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, vkoval, Вы писали:
V>В таком случаи все работает. Но не хочется из каждого файла что-то экспортировать, притом таких файлом не мало.
Ну можно экспортировать что-то такое, что не жалко.
V>Надеялся, что есть более простой способ.
Почитай что модно писать в __declspec, может что и подойдёт...
V>Кстати, с dll тоже работает, но нужна именно статическая библиотека.
Про dll понятно, как раз.
есть ещё и второй сопсоб -- заиметь в соответсвующих хедерах какой-то код, который неявно ссылается на нужный cpp...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>Ты ставишь противоречивую задачу: если объект нигде не используется, то компилятор и не будет его создавать. Поэтому нужно либо явно использовать объект, либо как-то обмануть компилятор, тем же экспортом.
Тем не менее, если просто cpp в проект включить, а не через статическую библиотеку, то коспилятор таки как-то решает "противоречивую задачу"
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
ГВ>>Ты ставишь противоречивую задачу: если объект нигде не используется, то компилятор и не будет его создавать. Поэтому нужно либо явно использовать объект, либо как-то обмануть компилятор, тем же экспортом.
E>Тем не менее, если просто cpp в проект включить, а не через статическую библиотеку, то коспилятор таки как-то решает "противоречивую задачу"
Дык, главное тут — сделать правильные предположения о предположениях компилятора.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>Дык, главное тут — сделать правильные предположения о предположениях компилятора.
Компилятор известен, так что никаких предположений делать не надо. Надо MSDN почитать...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>>Ты ставишь противоречивую задачу: если объект нигде не используется, то компилятор и не будет его создавать. Поэтому нужно либо явно использовать объект, либо как-то обмануть компилятор, тем же экспортом.
E>Тем не менее, если просто cpp в проект включить, а не через статическую библиотеку, то коспилятор таки как-то решает "противоречивую задачу"
Вот тут объясняется почему так происходит: http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/2aa2e1b7-6677-4986-99cc-62f463c94ef3
FYI: gcc можно настроить чтобы он не умничал и включал в exe/dll все объектники из статических библиотек (--whole-archive).
Здравствуйте, alsemm, Вы писали:
A>Вот тут объясняется почему так происходит: http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/2aa2e1b7-6677-4986-99cc-62f463c94ef3
То, что это фича статических библиотек описано прямо в MSDN было когда-то. Сейчас лень искать в современном.
И эта фича более или менее по делу, так как из многих библиотек много-много мусора подтянется, если сделать иначе...
A>FYI: gcc можно настроить чтобы он не умничал и включал в exe/dll все объектники из статических библиотек (--whole-archive).
А как быть с мусором из других библиотек?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, vkoval, Вы писали:
V>Здравствуйте!
V>Возникла проблема при использовании глобальных объектов. V>В Static Library есть некоторые количество глобальных объектов. Эти объекты являются "creator-ми" других объектов используемых через интерфейсы, иными словами глобальный объект отвечает за создание определенного экземпляра класса и добавляет его вместе с ключом в фабрику классов. На этом работа этих глобальных объектов заканчивается и только при уничтожении они удаляют класс, за который они отвечают, из фабрики классов.
В htmlayout точно таким образом подключаются behaviors. Каждый behavior это отдельный файл
и нужный набор behaviors определяется просто набором файлов включенных в проект.
Проблема была в том что при static lib и именно с MFC VS почему то выкидывала статические обхекты в release сборках.
В качестве решения — #pragma optimize( "", off ) вокруг класса-фабрики.
Все behaviors наследуются вот от этого:
#if defined(_MSC_VER) && (_MSC_VER / 100) >= 13
#pragma optimize( "", off )
#endif
struct behavior: event_handler
{
behavior(UINT subsriptions, const char* external_name)
:next(0),name(external_name), event_handler(subsriptions)
{
// add this implementation to the list (singleton)
next = root();
root(this);
}
// behavior list support
behavior* next;
const char* name; // name must be a pointer to a static string
// returns behavior implementation by name.static event_handler* find(const char* name, HELEMENT he)
{
for(behavior* t = root(); t; t = t->next)
if(strcmp(t->name,name)==0)
{
return t->attach(he);
}
return 0; // not found
}
// implementation of static list of behaviors static behavior* root(behavior* to_set = 0)
{
static behavior* _root = 0;
if(to_set) _root = to_set;
return _root;
}
// standard implementation of HLN_ATTACH_BEHAVIOR notificationstatic bool handle( LPNMHL_ATTACH_BEHAVIOR lpab )
{
htmlayout::event_handler *pb = htmlayout::behavior::find(lpab->behaviorName, lpab->element);
if(pb)
{
lpab->elementTag = pb;
lpab->elementProc = htmlayout::event_handler::element_proc;
lpab->elementEvents = pb->subscribed_to;
return true;
}
return false;
}
};
#if defined(_MSC_VER) && (_MSC_VER / 100) == 13
#pragma optimize( "", on )
#endif
Практика показала что это работает.
Можно попробовать найти конкретный флаг который отвчет за "выкидывающую" оптимизацию. Найдешь — дай знать плиз.
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, alsemm, Вы писали:
A>>Вот тут объясняется почему так происходит: http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/2aa2e1b7-6677-4986-99cc-62f463c94ef3 E>То, что это фича статических библиотек описано прямо в MSDN было когда-то. Сейчас лень искать в современном. E>И эта фича более или менее по делу, так как из многих библиотек много-много мусора подтянется, если сделать иначе...
A>>FYI: gcc можно настроить чтобы он не умничал и включал в exe/dll все объектники из статических библиотек (--whole-archive). E>А как быть с мусором из других библиотек? http://unixhelp.ed.ac.uk/CGI/man-cgi?ld:
--whole-archive
For each archive mentioned on the command line after the
--whole-archive option, include every object file in the archive in
the link, rather than searching the archive for the required object
files. This is normally used to turn an archive file into a shared
library, forcing every object to be included in the resulting
shared library. This option may be used more than once.
Two notes when using this option from gcc: First, gcc doesn't know
about this option, so you have to use -Wl,-whole-archive. Second,
don't forget to use -Wl,-no-whole-archive after your list of
archives, because gcc will add its own list of archives to your
link and you may not want this flag to affect those as well.
Здравствуйте, alsemm, Вы писали:
A>Здравствуйте, Erop, Вы писали:
E>>Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>>>Ты ставишь противоречивую задачу: если объект нигде не используется, то компилятор и не будет его создавать. Поэтому нужно либо явно использовать объект, либо как-то обмануть компилятор, тем же экспортом.
E>>Тем не менее, если просто cpp в проект включить, а не через статическую библиотеку, то коспилятор таки как-то решает "противоречивую задачу" A>Вот тут объясняется почему так происходит: http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/2aa2e1b7-6677-4986-99cc-62f463c94ef3
A>FYI: gcc можно настроить чтобы он не умничал и включал в exe/dll все объектники из статических библиотек (--whole-archive).
A>Алексей
А в заголовочный файл с описанием интерфейса класса (это интерфейс к объекту созданному тем самым «проблемным» глобальным объектом — creator), который подключается в MFC приложение, добавляем:
Из плюсов такой реализации стоит отметить:
1) Если приложение даже косвенно не использует глобальный объект из статической библиотеки, т. е. нет подключения заголовочного файла с интерфейсом, то объект не будет зря создан. Таким образом создание объекта контролируется включением его интерфейса в проект;
2) Теперь порядок создание глобальных объектов в статической библиотеке будет определен порядком включения их интерфейсных файлов.
V>Из плюсов такой реализации стоит отметить: V>1) Если приложение даже косвенно не использует глобальный объект из статической библиотеки, т. е. нет подключения заголовочного файла с интерфейсом, то объект не будет зря создан. Таким образом создание объекта контролируется включением его интерфейса в проект; V>2) Теперь порядок создание глобальных объектов в статической библиотеке будет определен порядком включения их интерфейсных файлов.
Интересный побочный эффект. Но только emptyreference@XXXEmptyReference@@YAXXZ может по разному выглеть на разных компиляторах, так что сопровождать такой код — морока.
Здравствуйте, vkoval, Вы писали:
V>Практически тоже самое что предложил Erop, только попроще.
Я предлагал ровно тоже самое. Только не обязательно именно функцию экспортировать. статический char экономнее будет...
Конструкцию с функциями invoke я предлагал на случай, если тебе не хочется экспортировать из своего приложения МНОГО мусора
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, alsemm, Вы писали:
A>Интересный побочный эффект. Но только emptyreference@XXXEmptyReference@@YAXXZ может по разному выглеть на разных компиляторах, так что сопровождать такой код — морока.
Да не надо так делать! Надо просто иметь в extern "C" глобальный char с уникальным длинным именем...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском