![]() |
|
|
![]()
|
|
| SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: нет Всего: 91 |
Есть программа, которая может работать как с плагином, так и без него. Плагин реализован в виде .dll файла.
Будет ли использоваться плагин или нет решается на этапе компиляции. Компилятор mingw. Плагин экспортирует ряд функций, которые вызывает основная программа. Сами функции плагина используют методы из основной программы, т.е. основная программа компилится как -shared и экспортирует ряд своих функций. Таким образом получается полное связывание: dll <-> exe К dll линкуется exe, к exe линкуется dll. У линковщика gcc есть ключ --out-implib=main.a, который позволяет помимо сборки .exe файла экспортировать библиотеку, которую можно прилинковать к плагину (dll). Т.к. получается замкнутый круг мне необходимо, чтобы линковщик не создавал .exe файла, а только экспортировал main.a файл, который я бы прилинковал к dll, а после этого собрал бы уже exe файл с прилинкованной dll.a библиотекой после сборки плагина. Сборка .exe файла идет таким образом:
Если убрать '-o"main.exe"', то все-равно создается файл "a.exe", мне нужен только main.a файл на данном этапе Это сообщение отредактировал(а) SABROG - 26.1.2008, 19:53 |
|||
|
||||
| archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: нет Всего: 93 |
SABROG, учитывая, что из себя представляет import library, боюсь, что такое невозможно. Необходимо провести декомпозицию и избавится от цикличной зависимости.
Могу я в очередной раз поинтересоваться, как Ваш пост относится к специфике данного раздела? -------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
| SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: нет Всего: 91 |
Часть названия ветки "Кроссплатформенное программирование".
У меня кроссплатформенный проект, который отлично собирается под nix'ами и в винде через MSVC. Я хочу сделать возможным собирать проект через mingw. Работа закончена на 70%. Насчет "невозможности" я не соглашусь, проект как-раз так и работал, собран он был лишь в msvc. Сейчас я пытаюсь понять как мне написать makefile для mingw, чтобы в правильной последовательности и без "хаков" заставить проект собираться... Цикличной зависимости не возникает, скорее всего потому, что сначала грузится main.exe, который в свою очередь подгружает статически слинкованную dllку, та в свою очередь пытается подгрузить снова main.exe, но ОС находит ее уже загруженной в память, поэтому цикл на этом прерывается. Это сообщение отредактировал(а) SABROG - 26.1.2008, 23:19 |
|||
|
||||
| archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: нет Всего: 93 |
Можно глянуть на hello world солюшн с циклической связью? (приаттачьте) Возможно, так будет проще помочь Вам. Можно попробовать удалять .exe после сборки, но я что-то сомневаюсь, что это будет работать(в плане makefile будет работать правильно, но, боюсь, не будет работать последующая линковка или сам бинарник). -------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
| SABROG |
|
||||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: нет Всего: 91 |
Ну с нуля писать hello world накладно, но я нашел наглядный пример - http://www.codeguru.com/cpp/w-p/dll/article.php/c3649/
Вроде как начало проясняться, plugin.dll статически линкует exe файл, exe файл динамически подгружает plugin.dll. Только сейчас косяк возник со статической линковкой exe файла:
В exe файле этот экспортируемый класс объявлен так:
Это сообщение отредактировал(а) SABROG - 27.1.2008, 00:09 |
||||
|
|||||
| archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: нет Всего: 93 |
В этом принципиальная разница, т.к. в случае, если оперировать GetProcAddress циклической зависимости не будет. Вам же требуется связывание, так сказать, на этапе компиляции. Вы утверждаете, что проделывали такое на c MSVC, вот я и прошу привести мне пример т.к. мне немного не верится, что такое возможно... -------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
| Любитель |
|
|||
|
Программист-романтик ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3645 Регистрация: 21.5.2005 Где: Воронеж Репутация: нет Всего: 92 |
||||
|
||||
| SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: нет Всего: 91 |
Ладно, похоже придется дальше самому ковыряться. Тему можно удалить.
Написал именно в этом разделе, потому, что нужен совет специалистов, которые работали как с MSVC так и с компилятором GCC. |
|||
|
||||
| archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: нет Всего: 93 |
SABROG, на мой взгляд, то что ты пытаешься сделать сродни двум хэдерам с перекрёстной зависимостью, но без forward declarations.
-------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
| SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: нет Всего: 91 |
Такое вот по какой причине обычно вылезает ?
В .def файле и в .a файле четко вижу наличие __imp___ZTV17FollowerReference. FollowerReference - класс. |
|||
|
||||
| archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: нет Всего: 93 |
-------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
| SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: нет Всего: 91 |
Добавлял уже, не помогает никак вообще, выводит тоже самое.
Попробывал метод без подключения .a, а просто переименовал main.exe -> libmain.dll и линкер его подцепил точно также как и .a и с теми же ошибками. Странно, обнаружил, что -export-all-symbols у меня, по какой-то причине, не включен по-умолчанию. После включения либа (main.a) разжирела на 8 мегов, исчезли проблемы с другими импортами, а вот именно с этим остались... --------- Углубился в тему. Немного разобравшись, понял где происходит косяк, но не понял как это исправить. Значит смысл такой, есть .exe файл в котором определен класс, этот .exe файл динамически загружает plugin.dll, а он в свою очередь статически слинкован с exe файлом. Так вот благодаря тому, что в хидерах описано определние класса из плагина создается экземпляр объекта через оператор new. Методы этого объекта находятся в exe файле. Не могу понять, почему MSVC все это хавает, а gcc не хочет:
Это сообщение отредактировал(а) SABROG - 27.1.2008, 19:31 |
|||
|
||||
| archimed7592 |
|
||||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: нет Всего: 93 |
SABROG, смотри, вот hello world пример(возможно, что неправильный):
Что я делаю неправильно? -------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
||||
|
|||||
| SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: нет Всего: 91 |
Забыл декорацию __declspec(dllexport) ?
Взял пример, на который выкладывал ссылку выше, и переделал его немного. Все собирается, но при вызове программы выдает "main.exe не является приложением Win32". Исходники тут http://filebeam.com/746ddc0026e738bcda9f20e2356edffe ------ Так, с main.exe я разобрался, ошибка была потому, что я его собирал с флагом -shared. Это сообщение отредактировал(а) SABROG - 28.1.2008, 18:41 |
|||
|
||||
| archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: нет Всего: 93 |
Не совсем, но не суть -------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
| SABROG |
|
||||||||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: нет Всего: 91 |
Обнаружил интересную особенность. Например нам надо экспортировать класс в dllку. Но класс находится в сторонней .a библиотеке, которая линкуется с .exe файлом, то такой класс не экспортируется, его нет в .def файле на выходе с main.exe. Но если точно такой же класс находится внутри main.exe, то он прекрасно экспортируется и внутри дллки я могу вызывать операторы new и delete, при этом конструктор находится внутри exe файла и сообщение на экран выводится именно с него. Возможно проблема где-то зарылась в отсутствии файла реализации класса (.o), который не линкуется к .exe.
Вот мой пример: http://filebeam.com/ca9f86187ea6f8d26a363926ef7ac22a --- Хмм, получилось. Из .a тоже вызывается теперь, главное при сборке class.a, чтобы стоял __declspec(dllexport) и тоже самое должно быть в main.exe при сборке. Если бы например при сборке class.a класс стоял бы просто как обычный не экспортируемый, а потом в main.exe стал бы экспортируемым, то это не сработало бы. Соответственно в dll.dll при подключении заголовков классов должно быть __declspec(dllimport). А при экспорте функции из dll в exe __declspec(export). Теперь предстоит разобраться как разное построение классов влияет на экспорт (наследование, шаблоны, виртуальные функции) --- Век живи - век учись. При импорте класса даже не нужно прописывать __declspec(dllimport) оказывается... Забавно. Более того, там может остаться __declspec(dllexport) и это будет работать. Похоже смысл есть только в экспорте, либо он есть либо нет. А уж то что ты импортируешь определяется линковкой. Кстати интересно почему тройное экспортирование не вышло, цепочка завершилась на .dllке, как экспортировала 1 функции так и осталось. --- Еще одна особенность. Если использовать .def файл, то классы не находятся:
А связано это с тем, что классы и данные не нужно импортировать, они автоматически импортируются. Поэтому удалив из .def файла все кроме статическх функций все линкуется и работает. --- Еще кое-что раскопал. Оптимизация прямым образом влияет на список экспортируемых данных. Например неиспользуемые переменные вырезаются, тоже самое с функциями и классами. Отключив оптимизацию полностью я обнаружил, что "подтянулись" еще некоторые экспортируемые данные, на которые, до этого, были ошибки. Но полностью проблемы это не решило. А чтобы компилить с оптимизацией надо либо вспоминать волшебное слово volatile, либо прописывать всегда __declspec(dllimport). --- Нашел показательный пример как получить undefined reference, проверил, работает:
Причем в этом случае не помогает ни отключение оптимизации ни __declspec(dllexport). Помогает только наличие хоть какого-нибудь кода внутри конструктора и деструктора:
--- Продвинулся дальше. Выяснил, что если создать базовый класс без конструктора, потом унаследовать его и ввести конструктор, то получаем:
--- Еще в копилку. Если в классе определен метод/конструктор/деструктор, но нигде не определена реализация, даже в виде пустой "{}", то снова возникает проблема с линковкой. Это сообщение отредактировал(а) SABROG - 31.1.2008, 17:42 |
||||||||
|
|||||||||
![]()
|
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | GNU toolchain | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |