dll и классы (dll-расширение)
#include <windows.h>
class MyDllClass{
public:
void (*Demo) (char *str);
};
main()
{
HINSTANCE h=LoadLibrary("DllClass.dll");
MyDllClass Obj;
Obj.Demo=(void (*) (char *str))
GetProcAddress(h,"Demo");
//выполняем конструктор
Obj.Demo("Test");
}
Т.е. после демангливания (через Def), как обратиться к переменной объекта класса (для каждого своя!)? Или нужно обязательно создавать
функции типа Get/Set? Вообще нигде! не написано про обращение к переменным dll (импорт из dll) при явной! загрузке (везде - только про функции - GetProcAddress). При неявной загрузке - проблем нет!
Мне нужно явно(!) подключить dll c классом, но я не знаю как в таком случае импортировать переменные! классов:
#include <windows.h>
class MyDllClass{
public:
void (*Demo) (char *str);
};
main()
{
HINSTANCE h=LoadLibrary("DllClass.dll");
MyDllClass Obj;
Obj.Demo=(void (*) (char *str))
GetProcAddress(h,"Demo");
//выполняем конструктор
Obj.Demo("Test");
}
Т.е. после демангливания (через Def), как обратиться к переменной объекта класса (для каждого своя!)? Или нужно обязательно создавать
функции типа Get/Set? Вообще нигде! не написано про обращение к переменным dll (импорт из dll) при явной! загрузке (везде - только про функции - GetProcAddress). При неявной загрузке - проблем нет!
1. Непонятно почему вопрос в разделе Win32API.
2. Что значит "демангливания"? Пишите либо по-русски, либо по-английски.
3. Экземпляр класса находится в памяти, а не в DLL. Так что мешает обращаться к его полям? Ты же сделал это с полем Demo
Obj.Demo = ............
Кстати, правильно ли ты понимаешь термин "явная загрузка". Явная, это как раз через LoadLibrary с последующим GetProcAddress.
Так вот: в DLL можно экспортировать класс, и потом
даже наследовать от него-если подключиться неявно
(сослаться на LIB-ку). Т.к. компилятор разукрашивает (манглит/mangle) имена функций, то для того, чтобы обращаться к dll из другой среды, нужно это предотвратить с помощью DEF-файла. После этого функции теряют связи с классом, да даже и без демангливания я не знаю как обращаться к классу при явной загрузке dll (нет же функции GetClassAddress/GetClass или типа того). То ли дело-динамическая загрузка сборок в .NET - можно все что угодно сделать! Неужели нельзя собрать класс по кусочкам (с нестатическими! переменными!) Типа такого:
class dllclass{...};
...
h=LoadLibrary(...);
...
dllclass obj=CreateObjectInProcessMemoryByClassNameWhichDefinedInExternDLL(h,"dllclass"...)
...
Или быть может я многого хочу, может существуют ограничения? Т.Е. если укажу для каждого объекта (как в примере выше) указателями на одни и теже функции описанные в DLL, то меня это не устроит - ведь они должны работать с полями конкретного экземпляра класса! (как до них добраться - это уже второй вопрос)
Хотя все функции сделать виртуальными и экспортировать таблицу виртуальных методов, а потом явно её перезаписывать в экземпляре объекта, может что и получится. Только чтобы компилятор не ругался, все функции должны присутствовать в виде пустышек.
Вопрос относится именно к WinAPI (процессы, потоки, объекты ядра, дин. библиотеки и др.), непосредственно к DLL (не к COM).
Я кажется понял суть твоего вопроса. И все же считаю, что он не относится непосредственно к Win32 API, а скорее к специфике используемого компилятора.
Так вот: в DLL можно экспортировать класс, и потом
даже наследовать от него-если подключиться неявно
(сослаться на LIB-ку). Т.к. компилятор разукрашивает (манглит/mangle) имена функций, то для того, чтобы обращаться к dll из другой среды, нужно это предотвратить с помощью DEF-файла.
Спасибо за ликбез, но тебе достаточно было употребить слово "декорирование".
После этого функции теряют связи с классом, да даже и без демангливания я не знаю как обращаться к классу при явной загрузке dll (нет же функции GetClassAddress/GetClass или типа того). То ли дело-динамическая загрузка сборок в .NET - можно все что угодно сделать! Неужели нельзя собрать класс по кусочкам (с нестатическими! переменными!) Типа такого:
class dllclass{...};
...
h=LoadLibrary(...);
...
dllclass obj=CreateObjectInProcessMemoryByClassNameWhichDefinedInExternDLL(h,"dllclass"...)
...
Или быть может я многого хочу, может существуют ограничения? Т.Е. если укажу для каждого объекта (как в примере выше) указателями на одни и теже функции описанные в DLL, то меня это не устроит - ведь они должны работать с полями конкретного экземпляра класса! (как до них добраться - это уже второй вопрос)
Ответ на первый вопрос:
для вызова методов-членов в данном случае надо использовать ->* и .*
(Obj.*Demo)("Test");
кстати, не забудь импортировать и вызвать конструктор для соотв. класса аналогичным образом.
Ответ на втророй вопрос:
для получения доступа к переменным класса можно использовать тот же GetProcAddress
int *pVar;
pVar = (int*)GetProcAddress(hLib, "Var");
Это все описано здесь:
http://www.rsdn.ru/article/baseserv/dlluse.xml
P.S. Хотя, я не вижу особого смысла всего этого, помоему проще использовать фабрики.
Мне нужно явно(!) подключить dll c классом, но я не знаю как в таком случае импортировать переменные! классов:
#include <windows.h>
class MyDllClass{
public:
void (*Demo) (char *str);
};
main()
{
HINSTANCE h=LoadLibrary("DllClass.dll");
MyDllClass Obj;
Obj.Demo=(void (*) (char *str))
GetProcAddress(h,"Demo");
//выполняем конструктор
Obj.Demo("Test");
}
Т.е. после демангливания (через Def), как обратиться к переменной объекта класса (для каждого своя!)? Или нужно обязательно создавать
функции типа Get/Set? Вообще нигде! не написано про обращение к переменным dll (импорт из dll) при явной! загрузке (везде - только про функции - GetProcAddress). При неявной загрузке - проблем нет!
Если не ошибаюсь, то в МСДН сказано, что dll может экспортировать только ф-ции и глобальные переменные. Если нужно получить класс, то надо хитрить: в программе объявляется УКАЗАТЕЛЬ на класс, а в dll - ф-ция, которая будет этот класс создавать и возвращать указатель на него. Короче - все как в COM (CreateInstance).
// mydll.cpp
#include "stdafx.h"
class __declspec(dllexport) dllclass
{
public:
int j;
void __cdecl Demo(int val);
};
void dllclass::Demo(int val)
{
j=val; //<<Вниание сюда!
}
...
#include "windows.h"
#include "stdafx.h"
#include <afxwin.h>
class _dllclass{
public:
int j;
void (__cdecl *Demo)(_dllclass* ,int);
void _Demo(int Var);
};
void _dllclass::_Demo(int Var)
{
Demo(this,Var);
}
int main(int argc, char* argv[])
{
HINSTANCE h=LoadLibrary("mydll.dll");
_dllclass obj;
obj.Demo=(void (*) (_dllclass* ,int)) GetProcAddress(h,"Demo");
obj._Demo(10);
return 0;
}
...
Вот такие пироги...
И все таки я извратился! Меня интересовало то, как будет работать функция с внутренним членом класса если она потеряфет связь с классом при динамической загрузке с def-файлом? А никак! Бех хитростей будет Access Violation! Но т.к. компилятор преобразует методы классов в обычные методы с передачей в них this через стек, то можно замутить вот такое:
// mydll.cpp
#include "stdafx.h"
class __declspec(dllexport) dllclass
{
public:
int j;
void __cdecl Demo(int val);
};
void dllclass::Demo(int val)
{
j=val; //<<Вниание сюда!
}
...
#include "windows.h"
#include "stdafx.h"
#include <afxwin.h>
class _dllclass{
public:
int j;
void (__cdecl *Demo)(_dllclass* ,int);
void _Demo(int Var);
};
void _dllclass::_Demo(int Var)
{
Demo(this,Var);
}
int main(int argc, char* argv[])
{
HINSTANCE h=LoadLibrary("mydll.dll");
_dllclass obj;
obj.Demo=(void (*) (_dllclass* ,int)) GetProcAddress(h,"Demo");
obj._Demo(10);
return 0;
}
...
Вот такие пироги...
Но при таком подходе есть одно НО. Тебе необходимо иметь ДВА описания по сути одного и того же класса: с обычными методами для dll и с указателями на методы - для программы. В СОМ-подходе нужен только ОДИН хедер, который вставляется и в программу, и в dll, что упрощает изменения в коде. Хотя, если подумать, то можно упростить изменения и при 2-х определениях класса.