Поиск:

Ответ в темуСоздание новой темы Создание опроса
> VS2005 и Dll, Где потерялась DllMain 
V
    Опции темы
takedo
Дата 26.7.2007, 13:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 501
Регистрация: 1.6.2005

Репутация: нет
Всего: 3



Создал визардом VS2005 проект Dll, а функция DllMain не сгенерировалась. Раньше, в VS6 функция автоматом прописывалась. Попробовал добавить вручную, куча ошибок компилятора выскочила. В поиске нашел темку похожую, но там только сказали, что тема знакомая - куча макросов МФЦ, содержащих обращение к DllMain, но ничего никто не объяснил. Может кто сможет толком объяснить как прописать DllMain без проблем? 
PS.: Фукнция мне реально нужна, заглушка не устраивает


--------------------
я не гольфист - я хоккеист
PM MAIL   Вверх
W4FhLF
Дата 26.7.2007, 13:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: нет
Всего: 121



Код

#include <windows.h>

bool DllMain (HANDLE hInst,DWORD dwReason, LPVOID IpReserved) 
{
    switch (dwReason) {
        case DLL_PROCESS_ATTACH: // Инициализация процесса.
            break; 
        case DLL_THREAD_ATTACH: // Инициализация потока.
            break;
        case DLL_THREAD_DETACH: // Очистка структур потока.
            break;
        case DLL_PROCESS_DETACH: // Очистка структур процесса.
            break;
    }
    return TRUE;
}



--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
takedo
Дата 26.7.2007, 13:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 501
Регистрация: 1.6.2005

Репутация: нет
Всего: 3



вопрос лишь в том в какой файл это вставить. Я вставил функцию в единственный сгенерированных файл, но посыпались ошибки. Отличие было в том, что я не прописывал windows.h Ладно, надо идти пробовать...


--------------------
я не гольфист - я хоккеист
PM MAIL   Вверх
W4FhLF
Дата 26.7.2007, 13:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: нет
Всего: 121



Не знаю, может людям имеющим дело в MFC будет понятно и так, но без лога компиляции у меня никаких мыслей дальнейших не возникает. 


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
Earnest
Дата 26.7.2007, 16:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



takedo, ту какой проект генерировал? Может MFC, но не Extension DLL? Тогда и не должно появиться DLLMain. Т.е. она, конечно, есть, но не в твоем коде...
Ты бы просто собрал полученный проект, может он нормально собирается...


--------------------
...
PM   Вверх
takedo
Дата 26.7.2007, 16:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 501
Регистрация: 1.6.2005

Репутация: нет
Всего: 3



Вставляю функцию и получаю:

1>Linking...
1>uafxcwd.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in subd01.obj
1>   Creating library d:\programs\bases1\subd01\Debug\subd01.lib and object d:\programs\bases1\subd01\Debug\subd01.exp
1>d:v\programs\bases1\subd01\Debug\subd01.dll : fatal error LNK1169: one or more multiply defined symbols found

Проект не extension dll. Вот и как от этого избавляться не знаю smile 


--------------------
я не гольфист - я хоккеист
PM MAIL   Вверх
Earnest
Дата 26.7.2007, 17:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Без ручной доводки напильником собирается?

Вариантов я вижу 2: 
1) сделать проект заново, MFC Extension DLL. Тогда возделенная DLLMain будет.
2) понять, действительно ли тебе так нужна DllMain. Если у тебя проект MFC Regular DLL, то у тебя в основном файле должен быть объект-наследник CWinApp, у которого есть виртуальные функции InitInstance и ExitInstance. Которые, в свою очередь, вызываются из внутренней DllMain в начале и конце. Читай Tech Note 11.

Но, имей в виду, при использовании Regular DLL есть некоторые тонкости с ресурсами... Обычно Extension DLL в связке с MFC пользоваться удобнее.


--------------------
...
PM   Вверх
takedo
Дата 26.7.2007, 17:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 501
Регистрация: 1.6.2005

Репутация: нет
Всего: 3



такс, объект-наследник CWinApp есть. Попробую создать Extension DLL, но такие dll кажется не могут внедрить в себя все необходимые функции из mfc, то есть прийдется таскать с собой mfcшные dll. Или я осень ошибаюсь?


--------------------
я не гольфист - я хоккеист
PM MAIL   Вверх
Earnest
Дата 26.7.2007, 17:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Нет, не ошибаешься. Правда, я не уверена, что Regular DLL в этом не нуждается, но вероятность такая есть... Почитай tecnical Note. Если тебе нужна отдельная DLL, которая подключается к чему угодно (а не обязательно к MFC-приложению), то это, конечно, Regular. Ну так и делай то, что тебе надо  на InitInstance и ExitInstance, в чем проблема-то? Почему обязательно нужна DllMain?


--------------------
...
PM   Вверх
takedo
Дата 10.8.2007, 09:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 501
Регистрация: 1.6.2005

Репутация: нет
Всего: 3



Нашёл интересный материал по адресу andy.uvarov.ru. Есть там книга по VisualC++ для начинающих. Там есть глава 12 - про Dll. И есть там непонятные мне абзацы: 
Цитата

Имеется два уровня использования структуры MFC в DLL. Первый из них — это обычная динамическая библиотека на основе MFC, MFC DLL (regular MFC DLL). Она может использовать MFC, но не может передавать указатели на объекты MFC между DLL и приложениями. Второй уровень реализован в динамических расширениях MFC (MFC extensions DLL).

или вот ещё:
Цитата

Однако обычные DLL не могут обмениваться с приложениями указателями на классы, производные от MFC.

То есть не могу понять толком, что же значит обмен Dll с приложением указателем на классы, производные от MFC?? smile  Так ли я понимаю, что если в Dll есть функция, использующая, например класс CMainObject : CObject, в качестве параметра, то надо делать Dll расширение?

Свою задачку я сделал через обычную статическую Regular Dll и мне в принципе все понравилось и устроило. В Dll есть несколько классов и пара функций, которые я экспортирую и применяю в приложении. Но не все гладко, есть ругательства компилятора при сборке Dll, они правда warning, но очень хочется знать чего это?
:
Цитата

1>d:\dlltest\regular\bd01red\bd01red\bdm01.h(39) : warning C4251: 'fmBase::cs' : class 'CCriticalSection' needs to have dll-interface to be used by clients of class 'fmBase'
1>        c:\program files\microsoft visual studio 8\vc\atlmfc\include\afxmt.h(150) : see declaration of 'CCriticalSection'
1>d:\dlltest\regular\bd01red\bd01red\bdm01.h(41) : warning C4251: 'fmBase::file_ctl' : class 'CFile' needs to have dll-interface to be used by clients of class 'fmBase'
1>        c:\program files\microsoft visual studio 8\vc\atlmfc\include\afx.h(1147) : see declaration of 'CFile'

класс выглядит примерно так:

Код

class AFX_CLASS_EXPORT fmBase
{
    CCriticalSection cs;

    CFile file_ctl;

ну и там дальше ещё куча функций. Так вот на каждый класс MFC вылазит однотипное (см. выше) сообщение компилятора.
Таким образом, если кто знает прошу Вас обяснить:
1) когда же все таки надо использовать Regular Dll, а когда есть смысл Extension?
2) Что за ошибки выдает компилятор? 


--------------------
я не гольфист - я хоккеист
PM MAIL   Вверх
Earnest
Дата 10.8.2007, 11:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Цитата(takedo @  10.8.2007,  10:31 Найти цитируемый пост)
То есть не могу понять толком, что же значит обмен Dll с приложением указателем на классы, производные от MFC??   Так ли я понимаю

Нет, в твоем источнике написано не совсем удачно. Речь идет только о тех объектах, которые известны MFC-оболочке: фреймы, вью, документы и прочая. И то, при некоторой доводке напильником все возможно. Эту фразу следует понимать примерно так: если у тебя Extension DLL, то все происходит точно так же, как если бы ты писал код в одном модуле. А с Regular DLL это не так. Дело в том, что каждый MFC-модуль (т.е. объект, производный от CWinApp или CWinThread  - точно не помню, кто именно) - таскает с собой списки созданных окон и еще кучу всего. Проблемы с Regular DLL возможны следующие: создал ты окно в главном модуле, а в DLL хочешь к нему как-то обратиться. Если ты передашь указатель на CWnd*, то большинство функций будет работать нормально (кроме разрушения). Но есть функции, которые проверяют, соответствует ли хандл окна указателю на объект (и проверяют это через список своего модуля). Вот с ними будут проблемы. Опять же, если у тебя есть хандл, и ты хочешь получить указатель на объект через CWnd::FromHandle, то в другом моделе ты получишь шиш с маслом (или временный объект, а вовсе не тот, на который расчитываешь).

С собственными классами, производными от CObject, можешь делать что хочешь, если не используешь их COM-возможности. Будут ли работать последние - я не знаю, не использовала. Классы, не производные от CObject - вообще все твое. Нужно только иметь в виду тонкости с разрушением динамических объектов: если модули используют разные экземпляры ран-тайма, то разрушение объекта должно происходить там же (в том же модуле), что и создание. Но лучеш, конечно, чтобы все пользовались общей копией динамической ран-тайм DLL.

Насчет предупреждений компилятора:
Видимо, при подсоединении к Regular DLL CCriticalSection и прочие не экспортируются.
Строго говоря, Regular DLL использует MFC только для собственных нужд, а не ре-экспортирует ее интерфейсы, как это происходит в Extension.

Проще всего от этого избавиться, экспортировав не весь класс целиком, а только необходимые функции.
Т.е. так:
Код

class fmBase
{
public:
   AFX_CLASS_EXPORT void SomeFunction();

private:
    CCriticalSection cs;
    CFile file_ctl;
};

Это, кстати, даст дополнительную гарантию насчет корректного создания\разрушения, т.к. конструктор и деструктор ты не экспортируешь. И лучше сделать это явно, т.е. написать конструктор и деструктор, даже если они пустые.


--------------------
...
PM   Вверх
takedo
Дата 10.8.2007, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 501
Регистрация: 1.6.2005

Репутация: нет
Всего: 3



Earnest, сделал как ты сказала - предупреждения ушли. И что характерно приложение нормально отработало. НЕСМОТРЯ на то, что теперь я не поставил перед классом макрос AFX_CLASS_EXPORT, хотя он по ходу тождественнен __declspec (dllexport). Это нормальная практика экспортировать только функции класса, а работать с классом целиком? Это просто мне хочется доконца разобраться. И если я не экспортировал что-то (переменные или функции), находящиеся в классе, например private часть, это не скажется на работу экспортированных фукнций, ссылающихся при работе на неэкспортируемые? Это все можно проверить, но хочется увидеть теоретические доводы smile .
По поводу литературы: этот источник мне понравился, предлагаю и тебе взглянуть - оценить. Альтернатива ему для меня в последнее время - только ты(смущаюсь...). Даже несмотря на то, что ещё не до конца разобрался, ставлю закономерный знак арифметичесой операции smile 


--------------------
я не гольфист - я хоккеист
PM MAIL   Вверх
Earnest
Дата 10.8.2007, 12:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Цитата(takedo @  10.8.2007,  12:29 Найти цитируемый пост)
 Это нормальная практика экспортировать только функции класса, а работать с классом целиком? 

Нормальная.
Экспортировать класс - значит экспортировать все его функции, а также все функции вложенных объектов и статические данные. Просто в первом случае ты экспортируешь все одним махом (для ленивых), в том числе и закрытые члены, во втором - управляешь экспортом.
Реально экспортировать нужно только то, что прямо вызывает клиент, и что не объявлено инлайн. Все остальное вызывается уже из кода DLL.
Кстати, по поводу инлайна будь осторожен: конструкторы и деструкторы объявляй явно и внутри файла cpp (т.е. прячь).
В принципе, я бы вообще советовала избегать инлайна для экспортируемых классов, по крайней мере пока не разберешься полностью в происходящем. Т.к. инлайны имплементируются в вызывающем коде (т.е. в другом модуле), и могут вызвать всякие недоразумения. Скажем, есть паблик инлайн метод, который ты не экспортируешь, т.к. он инлайн. Но он, в свою очередь, вызывает какой-то приватный метод, не экспортированный. И линкер начинает орать насчет последнего, хотя вроде клиент его сам не вызывает.

Цитата(takedo @  10.8.2007,  12:29 Найти цитируемый пост)
этот источник мне понравился

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

Кстати, MSDN все же почитай про DLL - все же это первоисточник. Там написано действительно все, хотя сложновато конечно: во-первых, английский, а во-вторых - много букв. Я в свое время распечатала себе темы про DLL, так получилась солидная такая книга... Но куда деваться...  smile 



--------------------
...
PM   Вверх
takedo
Дата 10.8.2007, 12:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 501
Регистрация: 1.6.2005

Репутация: нет
Всего: 3



Earnest, Ещй раз спасибо, вроде бы теперь все более ли менее понятно стало. Про MSDN - ты конечно права, но как сама понимаешь с моим немецким тяжело... Поэтому читаю Рихтера, Мешкова, Earnestа. А по поводу источника - тебе там конечно ничего нового не почерпнуть, но как модератору форума возможно и будет польза(чтобы послать сразу туда smile  и не набивать на клаве буквицы). 
В общем, считаю для себя этот вопрос закрытым. Всем большое спасибо.


--------------------
я не гольфист - я хоккеист
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




[ Время генерации скрипта: 0.0671 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.