| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Системное программирование и WinAPI > dll-явное связывание + классы |
| Автор: Nastya 23.3.2005, 09:36 |
| Если в dll-модуле у меня описан некий класс. Как к нему добраться при явном свзывании (т.е. создать объект этого класса) и как для этого его в dll надо правльно объявлять. |
| Автор: bel_nikita 23.3.2005, 09:44 | ||
| Через __declspec(dllexport) и __declspec(dllimport) В dll экспорт, в программе импорт *.Н
Только __declspec(dllimport) заменить макросом, чтоб в ДЛЛ это был экспорт, а в программе импорт |
| Автор: Nastya 23.3.2005, 10:37 |
| Спасибо, но тут еще тиакая проблема, если функцию я получаю через GetProcAdress, как мне то же самое сделать для имени класса? Как таким же образом создать объект? |
| Автор: Fire-Plug 23.3.2005, 11:03 | ||||
Фигушки. Я бы сделал экспортируемую ф-цию, возвращающую указатель на объект класса, к-рый создается к-либо кодом, реализованным в DLL. Объявил бы интерфейс класса (без реализации) в его заголовочном файле. Т.е. что-то вроде:
ЗЫ: Отсюда до идеи COM уже совсем недалеко... |
| Автор: Fire-Plug 23.3.2005, 11:14 |
| Хотя, ваще-то попадалась мне какая-то статейка, где рассматривалось как можно с помощью GetProcAddress получить адрес конструктора класса... Вот не помню, где это я ее читал. Но это выёживание. Будьте проще и к вам потянутся люди. |
| Автор: Nastya 23.3.2005, 16:23 |
| Спасибо. А если без подключения .h файла, то как я поняла, без com никуда? |
| Автор: Fire-Plug 24.3.2005, 04:29 | ||||
Без объявления типа переменной(объект - это тоже переменная, тип к-рой определен пользователем) вообще никуда! Переменную неопределенного типа ни создать нельзя, ни ссылку/указатель получить. Исключение - указатель на тип void *. Но указатель void * - это не то, что нам нужно. Для доступа к методам класса нужно знать его интерфейс, т.е. знать какие ф-ции-члены там имеются и как объявлены (о прямом доступе к атрибутам класса - вообще речи нет, т.к. это плохой стиль, нарушающий принцип инкапсуляции). Поэтому, этот интерфейс надо откуда-то получить. Традиционно объявления классов помещаются в заголовочные файлы. Можно дать объявление класса и в cpp-файле, если это реализация нек-рого впомогательного класса, объекты к-рого за пределами реализации в данном cpp-файле иметь не требуется. Для COM-классов можно указать, чтобы компилер сгенерил заголовочный файл, содержащий объявление требуемого класса, используя его(класса) type library. Например, директива
требует используя содержимое библиотеки msxml4.dll сгенерить заголовочный файл с объявлениями соотв. COM-классов. |
| Автор: np9mi7 10.4.2005, 10:41 | ||
Nastya, а почему именно явное связывание? Есть ведь такая вещь как отложенная загрузка (правда если на BCB то там какой фишки нет
Кстати интересно, как при таком подходе деструктор объекта вызывается...??? Статья про которую говорил Fire-Plug находиться http://rsdn.ru/article/baseserv/dlluse.xml |
| Автор: Fire-Plug 12.4.2005, 08:00 | ||
Тут уместно применить принцип: "Я тебя породил, я тебя и убью". Т.е., если объект создается в коде DLL, то и уничтожаться он должен там же. Вариантов реализации можно предложить несколько. 1) Динамический объект помещается, например, в авто-указатель, к-рый жив покуда DLL не выгружена. 2) Можно удалять объект по требованию. Тогда нужно будет добавить в DLL экспортируемую ф-цию для уничтожения объекта, передавая в кач-ве параметра его адрес. В DLL хранить объект в нек-ром контейнере, где он разыскивается с целю приведения приговора в исполнение. 3) Можно 2) реализовать путем заимствования идеи COM в плане подсчета ссылок. Тогда лучше возвращать указатель не на сам объект, а объект типа COM-указателя для целевого класса, для к-рого нужно будет добавить методы аналогичные AddREf() и Release(). А в DLL реализовать механизм для хранения и удаления объекта, если к-во его ссылок = 0. |
| Автор: np9mi7 12.4.2005, 08:05 | ||||||
Мне кажеться тут лучше всего отложенная загрузка. |
| Автор: Guest 12.4.2005, 23:11 | ||||||
Это-то в коде, где реализован конкретный класс, т.е. в коде DLL? Не смешите меня.
Ничем не хуже, чем delete myObj. "не хорошим" - явл. только ситуация, в к-рой следует соблюдать договоренности, а именно, удалять обьект с помощью спец. экспортируемой ф-ции. Но и указатель на обьект был получен также с помощью другой спец. ф-ции, а не через new
Конечно можно, если охота для частной задачи писать реализацию обязательной части интерфейса и возиться с его регистрацией. |
| Автор: np9mi7 13.4.2005, 10:26 | ||||
|
| Автор: Fire-Plug 13.4.2005, 16:43 | ||
В коде DLL, конечно. |
| Автор: np9mi7 13.4.2005, 22:58 |
| ну, тогда твоему ptr нужен адрес деструктора объекта... Нет? |
| Автор: Fantasist 13.4.2005, 23:09 |
| Вообще, экспортируемые классы суть набор экспортируемых ими методов куда входят и конструкторы и деструкторы. Кажется вполне возможным написать обертку, которая будет грузить библиотеку с помощью LoadLibrary и вызывать методы через GetProcAddress (включая конструкторы и деструкторы). |
| Автор: Fire-Plug 14.4.2005, 04:43 | ||
В статье по вышеуказ. ссылке http://rsdn.ru/article/baseserv/dlluse.xml как раз и рассматривается конкрентная техника как это сделать. Хотя надо сразу сказать, что это достаточно неудобно. Потому и шла речь о том, чтобы в DLL реализовать класс(ы) и способ его создания (фабрику объектов или что угодно) и по запросу только получать указатель на объект нужного типа. В DLL также нужно реализовать мехнизм удаления объекта по запросу или просто при ее выгрузке. |
| Автор: chipset 15.4.2005, 22:20 | ||||||||
А в чём преимущество такого подхода? Почему бы просто не получать указатель на фабрику классов? Кстати, имхо, лучшим вариантом было бы:
А если обьектом пользуются сразу два процесса? Добавлено @ 22:21
А если два процесса на один обьект? |
| Автор: Fantasist 15.4.2005, 22:26 | ||||||
Из обязательной части там только IUnknown реализовать нужно, да и его реализацию можно сделать ATL'ем. Регестрировать тоже не обязательно, можно создавать объект напрямую вызывая DllGetClassObject. Хотя я бы возвращал указатель на экземляр из dll. А в самом классе создал бы метод Destroy, который бы удалял сам себя, и перегрузил бы delete для него, чтобы он происходил через вызов Destroy(). В этом случае даже если delete будет вызван в основном модуле для указателя полученного из dll, объект удалится в dll. Добавлено @ 22:29
Вопросы синхронизации к данной теме не относятся. К тому же, один объект не может быть использован в разных процессах ибо у них разное адресное пространство (ну, конечно, это возможно, но только после дополнительных телодвижений). Добавлено @ 22:31
Преимущество в том, что не надо думать, как правильно создать и удалить объект. |
| Автор: chipset 15.4.2005, 22:32 | ||||
Ещё ATL прикручивать...
Тогда это и есть мини-фабрика обьектов, как я её понимаю.. |
| Автор: Fire-Plug 18.4.2005, 07:57 | ||||
У каждого процесса - своя память, в т.ч. динамическая. Ф-цию DLL может вызывать фуева хуча процесссов.
Сейчас поищу ссылку на статейку, к-рая рассказывает, как память DLL отображается на адресное пространство процесса. Все переменные, что экспортируются из/создаются кодом DLL - уникальны в адресном пространстве данного процесса и процесами не разделяются (not shared). Иначе, спрашивается, нахрена нужна была бы куча механизмов IPC(Inter-Process Communication), ежели бы переменные из разных процессов так запросто можно было бы share-ть. А вот исполняемый код - разделяется всеми процессами, к-рые юзают данную DLL. Ну, че искать статейку? Ваще ее в MSDN можно было года 3-4 назад легко найти. Только вот назывется больно обидно "DLL for beginners". |