Многопроектный солюшен - как собрать в единый exe
От: suvolod Россия  
Дата: 19.02.11 17:44
Оценка:
Я пишу приложение с использованием mfc (на основе диалога со статически прилинкованной библиотекой mfc). Мое приложение условно можно разделить на две форточки — основное окно программы и окно настроек этой программы. И основное, и окно настроек содержит кучу классов. Например, окно настроек состоит из пяти вкладок (соответственно, на каждую вкладку есть класс + еще парочка на основное окно), в основном приложении классов еще больше. Сейчас в моей проге все классы свалены в одну кучу: и основная программа, и окно ее настроек представляют единый проект. Ориентироваться очень трудно... поэтому я хочу создать солюшен, в котором будут два проекта — для программы и для окна ее настроек. Трудность в том, что я хочу затем собрать этот солюшен в единый exe-файл. Бьюсь уже неделю, но пока ничего не получается.

1. Сперва я хотел сделать оба проекта exe-шниками, затем проект окна настроек преобразовать в lib (через настройки проекта VStudio) и радоваться жизни. Не получилось. преобразование exe-в lib проходит успешно. Либа подключется к основному проекту и все выполняется без ошибок, но вызов окна настроек по Dlg.DoModal() возвращает -1 (Dlg — это объект класса диалогового окна настроек, лежащего в lib-е).
2. Затем я попробовал сделать то-же самое, но уже не преобразуя готовый exe-проект, а создать dll-проект, создать в нем ресурс типа диалоговое окно, создать класс этого диалогового окна, а затем уже преобразовать его в lib-у. Я предполагал, что lib-библиотека по своему строю гораздо ближе к dll библиотеке, а значит у меня все получиться. В итоге у меня получилось создать солюшен из двух проектов (exe и dll), запихнуть в dll диалог и вызвать его из exe-шника. Но дальше дело не пошло. После превращения dll-проекта в lib сразу же полезли ошибки вроде:
error LNK2019: unresolved external symbol "__declspec(dllimport) void __cdecl Show(void)" (__imp_?Show@@YAXXZ) referenced in function "public: void __thiscall CEXEDlg::OnBnClickedButton1(void)" (?OnBnClickedButton1@CEXEDlg@@QAEXXZ)

... оно и правильно, ведь lib-библиотека не имеет собственного хендла и ничего не знает про __declspec(dllimport) / __declspec(dllexport) разделяемой dll. А удаление этих импорт/экспорт-определений вернуло меня назад: либа собирается, но из exe-проекта окно вызвать невозможно, Dlg.DoModal() возвращает -1.
3. А теперь вопрос? Кто-нибудь с этим сталкивался? Все-таки можно собрать солюшен из нескольких проектов в единый exe-файл? Или, перефразируя, как вызвать диалог из lib-библиотеки? Ссылку на статью, примерчик, просто подсказку — буду рад любой помощи. На всякий случай выкладываю свой пример (exe+dll в одном солюшене), может кто-то сможет преобразовать его в солюшен аля (exe+lib). Ссылка: http://files.mail.ru/7WK70K
Re: Многопроектный солюшен - как собрать в единый exe
От: ZegSoft Россия  
Дата: 19.02.11 18:56
Оценка:
Здравствуйте, suvolod, Вы писали:

S>Я пишу приложение с использованием mfc (на основе диалога со статически прилинкованной библиотекой mfc). Мое приложение условно можно разделить на две форточки — основное окно программы и окно настроек этой программы. И основное, и окно настроек содержит кучу классов. Например, окно настроек состоит из пяти вкладок (соответственно, на каждую вкладку есть класс + еще парочка на основное окно), в основном приложении классов еще больше. Сейчас в моей проге все классы свалены в одну кучу: и основная программа, и окно ее настроек представляют единый проект. Ориентироваться очень трудно... поэтому я хочу создать солюшен, в котором будут два проекта — для программы и для окна ее настроек. Трудность в том, что я хочу затем собрать этот солюшен в единый exe-файл. Бьюсь уже неделю, но пока ничего не получается.


S>1. Сперва я хотел сделать оба проекта exe-шниками, затем проект окна настроек преобразовать в lib (через настройки проекта VStudio) и радоваться жизни. Не получилось. преобразование exe-в lib проходит успешно. Либа подключется к основному проекту и все выполняется без ошибок, но вызов окна настроек по Dlg.DoModal() возвращает -1 (Dlg — это объект класса диалогового окна настроек, лежащего в lib-е).

S>2. Затем я попробовал сделать то-же самое, но уже не преобразуя готовый exe-проект, а создать dll-проект, создать в нем ресурс типа диалоговое окно, создать класс этого диалогового окна, а затем уже преобразовать его в lib-у. Я предполагал, что lib-библиотека по своему строю гораздо ближе к dll библиотеке, а значит у меня все получиться. В итоге у меня получилось создать солюшен из двух проектов (exe и dll), запихнуть в dll диалог и вызвать его из exe-шника. Но дальше дело не пошло. После превращения dll-проекта в lib сразу же полезли ошибки вроде:
S>
S>error LNK2019: unresolved external symbol "__declspec(dllimport) void __cdecl Show(void)" (__imp_?Show@@YAXXZ) referenced in function "public: void __thiscall CEXEDlg::OnBnClickedButton1(void)" (?OnBnClickedButton1@CEXEDlg@@QAEXXZ)
S>

S>... оно и правильно, ведь lib-библиотека не имеет собственного хендла и ничего не знает про __declspec(dllimport) / __declspec(dllexport) разделяемой dll. А удаление этих импорт/экспорт-определений вернуло меня назад: либа собирается, но из exe-проекта окно вызвать невозможно, Dlg.DoModal() возвращает -1.
S>3. А теперь вопрос? Кто-нибудь с этим сталкивался? Все-таки можно собрать солюшен из нескольких проектов в единый exe-файл? Или, перефразируя, как вызвать диалог из lib-библиотеки? Ссылку на статью, примерчик, просто подсказку — буду рад любой помощи. На всякий случай выкладываю свой пример (exe+dll в одном солюшене), может кто-то сможет преобразовать его в солюшен аля (exe+lib). Ссылка: http://files.mail.ru/7WK70K

Может ответ не совсем в тему, но зачем тебе разделять на несколько проектов?? Лучше навсти порядок в класса: объединить в пространства имен или использовать вложенные классы.
а насчет lib я думаю это все из-за MFC. Вообще MFC очень капризная в этом плане. Если бы использовал WTL например думаю никаких проблем не было бы. Поэтому лучше наведи порядок в классах. Много классов — это не так уж и страшно)
Re[2]: Многопроектный солюшен - как собрать в единый exe
От: suvolod Россия  
Дата: 19.02.11 19:30
Оценка:
Вообще, ответ "в тему". На самом деле мне надо как-то логически/визуально разделить ту кучу классов, которая есть сейчас на вкладке ClassView, на фукнциональные группы. Разбиение на отдельные проекты мне показалось наиболее очевидным и удобным решением.. тем более что: оттестировал я функционал окна настроек, откомпилировал его lib-ку — теперь можно про нее "забыть", а работать/подвергать перекомпиляции только проект самой программы. Разбиение на пространство имен неудобно тем, что везде при работе с окном настроек придется добавлять имя этого пространства + ::. не люблю такое... А про вложенные классы не совсем понял.. То есть ты предлагаешь в один класс добавить всю кучу классов, например, проекта окна настроек? Затем создать в программе объект этого класса и работать с ним? Но ведь во вкладке ClassView все это множество классов все равно будет отображаться линейно, в общей куче... Да и в программе это будет выглядеть также как с пространством имен, только вместо myNameSpace::MyClassОbject.MyFunc(...) я буду писать нечто вроде myGlobalClassObject.MyClassObject.MyFunc(...)
Re[3]: Многопроектный солюшен - как собрать в единый exe
От: ZegSoft Россия  
Дата: 19.02.11 20:23
Оценка:
Здравствуйте, suvolod, Вы писали:

S>Вообще, ответ "в тему". На самом деле мне надо как-то логически/визуально разделить ту кучу классов, которая есть сейчас на вкладке ClassView, на фукнциональные группы. Разбиение на отдельные проекты мне показалось наиболее очевидным и удобным решением.. тем более что: оттестировал я функционал окна настроек, откомпилировал его lib-ку — теперь можно про нее "забыть", а работать/подвергать перекомпиляции только проект самой программы. Разбиение на пространство имен неудобно тем, что везде при работе с окном настроек придется добавлять имя этого пространства + ::. не люблю такое... А про вложенные классы не совсем понял.. То есть ты предлагаешь в один класс добавить всю кучу классов, например, проекта окна настроек? Затем создать в программе объект этого класса и работать с ним? Но ведь во вкладке ClassView все это множество классов все равно будет отображаться линейно, в общей куче... Да и в программе это будет выглядеть также как с пространством имен, только вместо myNameSpace::MyClassОbject.MyFunc(...) я буду писать нечто вроде myGlobalClassObject.MyClassObject.MyFunc(...)


Ну например, у тебя есть CPropertySheet, который имеет кучу вкладок. Эти вкладки, кроме как в объекте CPropertySheet тебе создавать не надо. Соответственно их можно запихнуть в CPropertySheet и они будут вложенными в него. И при создании в объекте CPropertySheet этих вкладок не нужно будет указывать :: так как они и так в нем объявлены. Точно так же можно сделать и с другими классами, которые используются только в CPropertySheet (классы элементов управления и так далее).
Отображаться они будут не линейно, а именно внутри класса (см. рисунок).


Это очень удобно, поскольку позволяет не засорять глобальное пространство имен, ну и кроме того, классы оказываются сгруппированныйми и по смыслу и физически. Единственный недостаток, после такого объединения ClassWizzard вряд сможет корректно обрабатывать вложенные классы, так что добавлять и удалять функции придется вручную. Но для меня например, это не является большой проблемой.
Кроме того, можно же использовать папки для группировки классов. В том числе и вложенные папки. Это очень удобно!!
Кстати, добавлять везде :: вовсе не нужно!!! Для этого есть using и using namespace.

Допустим, есть такой вот класс


class A
{
public:
  A();
  ~A();

  class B
  {
    public:
      B();
      ~B();
  }
};





в *.cpp файле пишешь


using A::B;



После этого можешь спокойно реализовывать функции:


A::A()
{

}

A::~A()
{

}

B::B()
{

}

B::~B()
{

}



Кроме того, реализации классов А и B могу даже находиться в разных файлах.
Re: Многопроектный солюшен - как собрать в единый exe
От: suvolod Россия  
Дата: 20.02.11 07:11
Оценка:
Да, спасибо за пояснения, теперь понятнее стало. Обязательно попробую. И еще — меня в твоем сообщении очень заинтересовала строчка:

Кроме того, можно же использовать папки для группировки классов

Если я правильно понял, в твоем случае это папки "Диалоги" и "Приложение". Вообще, именно это мне и нужно реализовать в своем приложении. Как ты это сделал, да еще с использованием кириллицы? Я использую Visual C++ 2005, перерыл все контекстное меню ClassView, но команды вроде Add->New Folder там нет.
Re[2]: Многопроектный солюшен - как собрать в единый exe
От: suvolod Россия  
Дата: 20.02.11 07:24
Оценка:
Здравствуйте, suvolod, Вы писали:

S>Да, спасибо за пояснения, теперь понятнее стало. Обязательно попробую. И еще — меня в твоем сообщении очень заинтересовала строчка:

S>

S>Кроме того, можно же использовать папки для группировки классов

S>Если я правильно понял, в твоем случае это папки "Диалоги" и "Приложение". Вообще, именно это мне и нужно реализовать в своем приложении. Как ты это сделал, да еще с использованием кириллицы? Я использую Visual C++ 2005, перерыл все контекстное меню ClassView, но команды вроде Add->New Folder там нет.

Все, нашел то что хотел... надо было не в контекстном меню искать, а поднять глаза чуть выше. Большое спасибо за подсказки !.

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

По исходной теме у меня еще один вопрос появился. Если вы его внимательно читали, там я спросил:

S>Или, перефразируя, как вызвать диалог из lib-библиотеки?

Дело в том, что на одном из форумов человек, которого я считаю гуру (ходит в модераторах, неоднократно мне помогал), утверждает, что статическая библиотека не может содержать ресурсов. Но почему тогда студия 2005 мне это позволяет сделать? Создаю проект: File->New->Proect->Win32 Proect ->Static Library. Затем на вкладке Resource View -> клик правой кнопкой ->Add->Resource->Dialog. Далее все как обычно — создаю класс диалога, компилирую ... все проходит без ошибок и на выходе у меня lib-а.
Re[3]: Многопроектный солюшен - как собрать в единый exe
От: suvolod Россия  
Дата: 20.02.11 07:27
Оценка:
Все, нашел то что хотел... надо было не в контекстном меню искать, а поднять глаза чуть выше. Большое спасибо за подсказки !.

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

По исходной теме у меня еще один вопрос появился. Если вы его внимательно читали, там я спросил:

S>Или, перефразируя, как вызвать диалог из lib-библиотеки?


Дело в том, что на одном из форумов человек, которого я считаю гуру (ходит в модераторах, неоднократно мне помогал), утверждает, что статическая библиотека не может содержать ресурсов. Но почему тогда студия 2005 мне это позволяет сделать? Создаю проект: File->New->Proect->Win32 Proect ->Static Library. Затем на вкладке Resource View -> клик правой кнопкой ->Add->Resource->Dialog. Далее все как обычно — создаю класс диалога, компилирую ... все проходит без ошибок и на выходе у меня lib-а.
Re[4]: Многопроектный солюшен - как собрать в единый exe
От: ZegSoft Россия  
Дата: 20.02.11 08:58
Оценка:
Здравствуйте, suvolod, Вы писали:

S>Все, нашел то что хотел... надо было не в контекстном меню искать, а поднять глаза чуть выше. Большое спасибо за подсказки !.


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


S>По исходной теме у меня еще один вопрос появился. Если вы его внимательно читали, там я спросил:


S>>Или, перефразируя, как вызвать диалог из lib-библиотеки?


S>Дело в том, что на одном из форумов человек, которого я считаю гуру (ходит в модераторах, неоднократно мне помогал), утверждает, что статическая библиотека не может содержать ресурсов. Но почему тогда студия 2005 мне это позволяет сделать? Создаю проект: File->New->Proect->Win32 Proect ->Static Library. Затем на вкладке Resource View -> клик правой кнопкой ->Add->Resource->Dialog. Далее все как обычно — создаю класс диалога, компилирую ... все проходит без ошибок и на выходе у меня lib-а.


Я точно не знаю, так как никогда не задавался такой целью, возможно твой гуру и прав. Но могу лишь интутивно предположить, что в твоем случае при компиляции возникают конфликты ресурсов. Если бы в твоем основном приложении не было бы ресурсов, возможно все скомпилировалось нормально. Возможно именно поэтому Студия и позволяет тебе добавлять ресурсы в Static Library проект (студия ведь не знает заранее, где ты будешь использовать свою lib'у: в проекте с ресурсами или нет).
У меня сейчас времени на эксперименты нет, но можешь сам это проверить: создай пустой Win32 проект с поддержкой MFC, прилинкуй к нему свою lib'у и попробуй вызвать какой-нибудь диалог. Только будь осторожен с настройками компиляции проектов. Нужно чтобы многие опции совпадали. Если lib у тебя Debug, то и приложение должно быть Debug, есть lib-unicodе, то и приложение должно быть юникод и так далее. Иначе будут ошибки линковки. Кстати именно из-за этого я решил отказаться от lib везде, где это возможно. Потому что необходимо компилировать сразу кучу lib для разных настрек проекта, а это очень не удобно. Иногда бывает какую-то опцию компиляции не поменяшь и получаешь кучу ошибок линковки. И потом несколько часов мучаешься в поисках, что же ты сделал не так. Поэтому я придерживаюсь принципа — "если есть исходный код, компилируй его прямо в проекте", а не линкуй через Static Library.
Если будешь проводить такой "эксперимент", отпишись. Очень интересен результат.
Re[5]: Многопроектный солюшен - как собрать в единый exe
От: suvolod Россия  
Дата: 20.02.11 13:29
Оценка:
И все-таки у меня получилось.. На другом форуме подкинули ссылку на статью http://ru.w3support.net/index.php?db=so&id=531502]. Cоздал солюшен на основе mfc-диалога, в него добавил проект Win32 ->Static Library (c галкой mfc), в него добавил диалог, создал класс этого диалога. Отредактировал rc-файл через Resource View->правый клик по rc exe-проекта -> Resource Includes и в появившемся диалоге прописал пути до файлов lib-проекта:

в верхнем edite — #include "..\\LIB\\resource.h"
в нижнем — #include "..\\LIB\\LIB.rc"

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

Для тех, кто пойдет по моему пути, напомню, что в настройках проекта очень важно выбрать одинаковую версию CRT для exe и lib-проекта (я пользовался Multi-threaded Debug (/MTd)) + одинаковое значение настройки General->Use MFC (у меня стоит Use MFC in a Static Library), иначе вы встретитесь с непонятными ошибками при линковке солюшена.

Еще пара замечаний:
1/ Иногда проект почему-то не собирается по кнопке "Buil Solution", но отлично компилируется по отдельности — сначала lib, затем dll.
2/ В поисках решения периодически натыкался на топики о том, что при вызове диалога из dll часть элементов управления не отображается. Пока с этим не встречался, но если вдруг у кого-то такой косяк себя проявит — попробуйте в lib-проекте явно вызвать функцию InitCommonControls для инициализиации стандартных элеменетов и InitCommonControlsEx для инициализации расширенных элементов типа деревья. Ну и выкладываю сам тестовый примерчик аля (exe+lib) http://files.mail.ru/232VNF
Re[6]: Многопроектный солюшен - как собрать в единый exe
От: suvolod Россия  
Дата: 20.02.11 13:34
Оценка:
Что-то ссылка не открывается... а правки сообщений, как я понял, на rsdn нет.
Ладно, вот поправленная ссылка: http://ru.w3support.net/index.php?db=so&id=531502
Re[6]: Многопроектный солюшен - как собрать в единый exe
От: Игорь Вартанов Ниоткуда  
Дата: 11.03.11 22:43
Оценка: +1
Здравствуйте, suvolod, Вы писали:

S>И все-таки у меня получилось..


И все таки это сомнительно. Если собирается библиотека, в нее никак не могут попасть скомпилированные ресурсы. Просто потому что они компилируются не в объектный файл. Скомпилированные ресурсы могут быть влинкованы только в PE файл (т.е. exe или dll), но не в lib. Наверное именно это и пытался тебе сказать тот, которого ты считаешь гуру. Вообще-то гуру надо слушать, они плохому не научат.
---
С уважением,
Игорь
Re[6]: Многопроектный солюшен - как собрать в единый exe
От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
Дата: 19.03.11 14:58
Оценка:
Здравствуйте, suvolod, Вы писали:

S>в верхнем edite — #include "..\\LIB\\resource.h"

S>в нижнем — #include "..\\LIB\\LIB.rc"

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


Ты таким образом сложил все ресурсы в один модуль — в твой .exe. Однако, так не очень любят делать по двум причинам:

1. Приходится явно прописывать связи библиотек в файлах исходников (в одних только настройках проекта это сделать проще, чем в настройках и исходниках).
2. Из-за потенциальных конфликтов идентификаторов ресурсов в разных библиотеках, если у тебя несколько .lib-проектов и в каждом свой resource.h.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.