struct IMyClass
{
virtual void Method1() = 0;
virtual void Method2() = 0;
virtual void AddRef() = 0;
virtual void Release() = 0;
}
Как импортировать класс из DLL?
Как импортировать класс из DLL? Или как создать обьект, класс которго содержится в DLL?
DLL подключена динамически с помощью LoadLibrary.
Функцией GetProcAddress я получаю адреса функций, методов, и по-моему классов.
Здесь представлен код с помощью которого можно использовать функцию, которая содержится в DLL.
//My.cpp//файл приложения
::
hMyDll=::LoadLibrary("tstdll");//получаем адресс DLL
typedef int (WINAPI *PFN_MyFunction)(int);//не знаю
PFN_MyFunction pfnMyFunction;
pfnMyFunction=(PFN_MyFunction)::GetProcAddress(hMyDll,"MyFunction");//получаем адресс функции
int iCode=(*pfnMyFunction)(4);//используем функцию!!!
FreeLibrary(hMyDll);
::
Подскажите пожалуйста с помощью чего и как, по аналогии представленного кода, можно создать обьект или класс, если известен адресс класса в DLL.
Совершенно ясно, что всё что видно из Dll - это куча функций, поэтому информацию от типе от туда средствами языка никак не достать. Потому ответ - COM, тебя никто не заставляет регистрировать и так далее, просто надо использовать эти самые запросы интерфейсов и т.д. Но это я так понимаю, тебе не подходит, правильно, тебе, я так понимаю, нужно извлекать информацию от типе. Но, по-моему с обычной Dll тебе такого не сделать. Короче говоря надо использовать COM. Но если так уж надо скинь мне по мылу: [email]TommyAlice@gmail.ru[/email], или в асю: 580758, я там всё что знаю расскажу.
Переходи на Visual Studio 2003/2005 Там всё просто. Объявляешь класс как public и он доступен во всех assemblies то есть сборках. А com по моему шняга. Хотя я чес говоря в нем не пробовал.
[QUOTE=littlefrankie]Переходи на Visual Studio 2003/2005 Там всё просто. Объявляешь класс как public и он доступен во всех assemblies то есть сборках. А com по моему шняга. Хотя я чес говоря в нем не пробовал.[/QUOTE]COM - шняга? Это еще почему?
Не поддерживает межмодульного наследования, например.
1. Делаешь этот класс экспортируемым, а именно class __declspec(dllexport) Имя_класса
2. Инклюдишь его хидер там где он используется.
3. Прописываешь в свойствах линкера в additional dependencies: имя_длл.lib (lib полюбому должен будет создастся при сборке проекта длл-ки)
Вот и все
1. Это, компонентное, так сказать программирование поэтому там нет наследования реализации вообще, а оно для компоненттов типа COM вообще не нужно - используйте наследование интерфеса.
На счёт Visual Studio:
Там же используеться .NET, а раз так то и говорить нечего - ясно же что автору темы не это нужно.
На счёт __declspec - это долбанное Microsoft Specific, поэтому там с dllexport для классов запаришся. Вообще обычная Dll экпортирет только функции и всё остальное это уже не то.
1. Делаешь этот класс экспортируемым, а именно class __declspec(dllexport) Имя_класса
2. Инклюдишь его хидер там где он используется.
3. Прописываешь в свойствах линкера в additional dependencies: имя_длл.lib (lib полюбому должен будет создастся при сборке проекта длл-ки)[/QUOTE]
Я использую LoadLibrary для того чтобы по нужде загружать и выгружать ДЛЛ, а не с запуском-остановом приложения (в случае длл.lib) из-за ограничения ресурсов (оперативки).
А насчет СОМ - это темный лес для меня, а времени как всегда в обрез. Но думаю придется изучить.
[QUOTE=Tommy]На счёт __declspec - это долбанное Microsoft Specific, поэтому там с dllexport для классов запаришся. Вообще обычная Dll экпортирет только функции и всё остальное это уже не то[/QUOTE]
Тогда каким образом используется класс из ДЛЛ в случае неявной загрузки(длл.lib). По идее ДЛЛ одна, адреса те же, однако при неявной загрузке можем работать с классом, при явной нет? а с функциями хоть как можно! Обьясните в чем разница?
ch_andr Задайся вопросом :"Нахрона оно надо?" И все пройдет/(решится через ф-ции)
А насчет СОМ - это темный лес для меня, а времени как всегда в обрез. Но думаю придется изучить.
Тогда каким образом используется класс из ДЛЛ в случае неявной загрузки(длл.lib). По идее ДЛЛ одна, адреса те же, однако при неявной загрузке можем работать с классом, при явной нет? а с функциями хоть как можно! Обьясните в чем разница?[/QUOTE]Механизм-то по сути скорее всего один и тот-же, хотя и не факт. Методы класса будут в dll-ке, но только как отдельные функции, типа MyClass::MyClass() - это типа конструктор и следовательно ни как линкеру бедному не будет понятно, что они то и есть, те самые, которые нужно вызывать при обращении к методам MyClass. А вот если lib файл ему указать, то он все будет знать :)
Немного запутанно получилось... :)
Немного запутанно получилось... :)[/QUOTE]Кстати, есть еще один способ. Объявляешь базовый интерфейс для своего класса, помещаешь его в хидер, который доступен для твоего приложения, создаешь в дллельке экспортирумую функцию MyClass_CreateInstance, которая возвращает указатель на интерфейс IMyClass и юзаешь методы этотго интерфейса, вот и все.
Например так:
Код хидера:
Код:
Код класса и функции:
Код:
class MyClass : public IMyClass
{
private:
.
.
int refCount_;
.
public:
MyClass() : refCount(0) { ... }
.
.
virtual void Method1();
virtual void Method2();
virtual void AddRef() { refCount_ ++; }
virtual void Release() { if(!--refCount_) delete this; }
}
__declspec(ddlexport) IMyClass* MyClass_CreateInstance()
{
return new MyClass();
}
{
private:
.
.
int refCount_;
.
public:
MyClass() : refCount(0) { ... }
.
.
virtual void Method1();
virtual void Method2();
virtual void AddRef() { refCount_ ++; }
virtual void Release() { if(!--refCount_) delete this; }
}
__declspec(ddlexport) IMyClass* MyClass_CreateInstance()
{
return new MyClass();
}
Теперь, как этим классом пользоваться, допустим ты уже знаешь адрес функции MyClass_CreateInstance.
Код:
void SomeFunction()
{
.
.
.
IMyClass* pMyClass = MyClass_CreateInstance();
pMyClass->AddRef();
.
.
.
pMyClass->Release();
}
{
.
.
.
IMyClass* pMyClass = MyClass_CreateInstance();
pMyClass->AddRef();
.
.
.
pMyClass->Release();
}
AFX_EXT_CLASS
Это не мне надо, это задание такое!
Вот пример кода, как создавать обьект, класс которого в ДЛЛ, которая загружается динамически явно(через LoadLibrary).
MyClassInDll.h// при компилировании файл также подключается к приложению
Код:
#pragma once
#ifndef _DLL_PROJ_
#define _DLL_LIB __declspec(dllimport)
#else
#define _DLL_LIB __declspec(dllexport)
#endif // !defined(_DLL_PROJ_)
::
class _DLL_LIB CtstVrt
{
private:
TvrtState VrtData;
public:
CtstVrt(void);
virtual int InitVrt(Tinit &, dword );
virtual int RunVrt(TinpData &, ToutData &, dword );
virtual int PauseVrt(dword );
virtual int ExitVrt(int &);
~CtstVrt(void);
};
extern "C"
{
_DLL_LIB void *CreateCtstVrt();
_DLL_LIB void FreeCtstVrt();
}
#ifndef _DLL_PROJ_
#define _DLL_LIB __declspec(dllimport)
#else
#define _DLL_LIB __declspec(dllexport)
#endif // !defined(_DLL_PROJ_)
::
class _DLL_LIB CtstVrt
{
private:
TvrtState VrtData;
public:
CtstVrt(void);
virtual int InitVrt(Tinit &, dword );
virtual int RunVrt(TinpData &, ToutData &, dword );
virtual int PauseVrt(dword );
virtual int ExitVrt(int &);
~CtstVrt(void);
};
extern "C"
{
_DLL_LIB void *CreateCtstVrt();
_DLL_LIB void FreeCtstVrt();
}
MyExe.h
Код:
::
///========= Грузим DLL!!! =========================
if((hVrtDll=::LoadLibrary("MyClassInDll.dll"))==NULL)
{ // /* не удалось загрузить DLL */
}
else
{ /* приложение имеет право пользоваться функциями DLL через hVrtDll*/
}
pfnCreateCtstVrt = (PFN_CreateCtstVrt)::GetProcAddress(hVrtDll,"CreateCtstVrt");
pfnFreeCtstVrt = (PFN_FreeCtstVrt)::GetProcAddress(hVrtDll,"FreeCtstVrt");
CtstVrt *pClass=(CtstVrt *)pfnCreateCtstVrt();//создаем объект
pClass->InitVrt(initDat,Time);// пример вызова метода
::
//------- Выгружаем DLL-------------------------
if( hVrtDll!=0 ) ::FreeLibrary(hVrtDll);
::
///========= Грузим DLL!!! =========================
if((hVrtDll=::LoadLibrary("MyClassInDll.dll"))==NULL)
{ // /* не удалось загрузить DLL */
}
else
{ /* приложение имеет право пользоваться функциями DLL через hVrtDll*/
}
pfnCreateCtstVrt = (PFN_CreateCtstVrt)::GetProcAddress(hVrtDll,"CreateCtstVrt");
pfnFreeCtstVrt = (PFN_FreeCtstVrt)::GetProcAddress(hVrtDll,"FreeCtstVrt");
CtstVrt *pClass=(CtstVrt *)pfnCreateCtstVrt();//создаем объект
pClass->InitVrt(initDat,Time);// пример вызова метода
::
//------- Выгружаем DLL-------------------------
if( hVrtDll!=0 ) ::FreeLibrary(hVrtDll);
::
Вот код unmanaged .h:
#ifdef UNMANAGED_EXPORT
#define UNMANAGED_API __declspec(dllexport)
#else
#define UNMANAGED_API __declspec(dllimport)
#endif
class UNMANAGED_API CUnmanaged
{
public:
int nValue;
CUnmanaged();
};
.CPP:
#include "stdafx.h"
#include "Unmanaged.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
CUnmanaged::CUnmanaged()
{
nValue = 5;
}
И managed .h:
#include "Unmanaged.h"
public __gc class Managed
{
public:
int nValue;
Managed();
private:
CUnmanaged __nogc* p;
};
.CPP:
#include "stdafx.h"
#include "Managed.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
Managed::Managed()
{
p = new CUnmanaged();
nValue=p->nValue;
}
Вроде все путем, но в итоге получаю такую ошибку:
Error 2 error LNK2028: unresolved token (0A000009) "public: __thiscall CUnmanaged::CUnmanaged(void)" (??0CUnmanaged@@$$FQAE@XZ) referenced in function "public: __clrcall Managed::Managed(void)" (??0Managed@@$$FQ$AAM@XZ) Managed.obj
Всем спасибо за внимание, я просто либу не подключил :) уже все заработало :)