Экспорт/импорт DLL
От: iLLness  
Дата: 03.10.01 10:24
Оценка:
Не подскажете, в чем проблема? Есть две MFC Extension DLL, одна импортирует класс из другой. Класс наследуется от CObject, используется run-time class information. В заголовке класса экспортируемой DLL пишу AFX_EXT_CLASS. Все члены класса нормально импортируются, за исключением CMyClass::classCMyClass, необходимой для run-time info. Вторая DLL из-за этого не линкуется. Если этот член класса вручную прописать в *.DEF файле, то он импортируется, но не работает IsKindOf для этого класса...
Visual C++ 6.0 SP2. Может SP повыше установить?
Илья Лощинин
Re: Экспорт/импорт DLL
От: PSP Беларусь  
Дата: 04.10.01 16:15
Оценка:
Здравствуйте iLLness, вы писали:

LL>Не подскажете, в чем проблема? Есть две MFC Extension DLL, одна импортирует класс из другой. Класс наследуется от CObject, используется run-time class information. В заголовке класса экспортируемой DLL пишу AFX_EXT_CLASS. Все члены класса нормально импортируются, за исключением CMyClass::classCMyClass, необходимой для run-time info. Вторая DLL из-за этого не линкуется. Если этот член класса вручную прописать в *.DEF файле, то он импортируется, но не работает IsKindOf для этого класса...

LL>Visual C++ 6.0 SP2. Может SP повыше установить?

Это конечно очень и очень рекомендуется.

Но..

Ты в объявлении классов DECLARE_DYNCREATE писал?
Всегда Ваш, PSP.
Re[2]: Экспорт/импорт DLL
От: iLLness  
Дата: 04.10.01 17:42
Оценка:
Здравствуйте PSP, вы писали:

PSP>Это конечно очень и очень рекомендуется.


Я посмотрел на майкрософтовском сайте — там SP весом по 30 мег, а то и больше.. Они такие и есть? :)

PSP>Ты в объявлении классов DECLARE_DYNCREATE писал?


Конечно писал, точнее DECLARE_SERIAL и IMPLEMENT_SERIAL где полагается. Я промоделировал свою ситуацию на чистом проекте, и вышло такое:
Если импортировать класс из MFC Extension в *.EXE, то он импортируется на ура и все run-time class info работает замечательно.
Если импортировать класс из одной MFC Extension в другую (в первой реализация родительского класса, во второй реализация наследованного), то появляется ошибка при линке — unresolved external и т.п. на переменную CMyClass::classCMyClass... Если прописать эту переменную в *.DEF, то ошибки не возникает, но связи не работают..
По-моему, налицо либо недоработка техники AFX_EXT_CLASS, либо баг. Поможет ли если импортировать с помощью __dllimp ?
Илья Лощинин
Re[3]: Экспорт/импорт DLL
От: PSP Беларусь  
Дата: 05.10.01 06:10
Оценка:
Здравствуйте iLLness, Вы писали:

LL>Здравствуйте PSP, вы писали:


PSP>>Это конечно очень и очень рекомендуется.


LL>Я посмотрел на майкрософтовском сайте — там SP весом по 30 мег, а то и больше.. Они такие и есть? :)


PSP>>Ты в объявлении классов DECLARE_DYNCREATE писал?


LL>Конечно писал, точнее DECLARE_SERIAL и IMPLEMENT_SERIAL где полагается. Я промоделировал свою ситуацию на чистом проекте, и вышло такое:

LL> Если импортировать класс из MFC Extension в *.EXE, то он импортируется на ура и все run-time class info работает замечательно.
LL> Если импортировать класс из одной MFC Extension в другую (в первой реализация родительского класса, во второй реализация наследованного), то появляется ошибка при линке — unresolved external и т.п. на переменную CMyClass::classCMyClass... Если прописать эту переменную в *.DEF, то ошибки не возникает, но связи не работают..
LL> По-моему, налицо либо недоработка техники AFX_EXT_CLASS, либо баг. Поможет ли если импортировать с помощью __dllimp ?

В MFC-шных исходниках написано DECLARE_DYNAMIC.

The DECLARE_DYNCREATE macro includes all the functionality of
DECLARE_DYNAMIC.

Кажется нашёл, что тебя спасёт, кусок из MSDN:

Limitations of _AFXEXT
You can use the _AFXEXT pre-processor symbol for your extension DLLs as long as you do not have multiple layers of extension DLLs. If you have extension DLLs that call or derive from classes in your own extension DLLs, which then derive from the MFC classes, you must use your own preprocessor symbol to avoid ambiguity and linker errors such as the following:
Wnd3.obj : error LNK2001: unresolved external symbol "protected: static struct AFX_MSGMAP const CWnd2::messageMap" (?messageMap@CWnd2@@1UAFX_MSGMAP@@B)
The problem is that in Win32, you must explicitly declare any data as _declspec(dllexport) if it is to be exported from a DLL, and declare any data as _declspec(dllimport) if it is to be imported from a DLL. When you define _AFXEXT, the MFC headers make sure that AFX_EXT_CLASS is defined correctly. When you have multiple layers, one symbol such as AFX_EXT_CLASS is not sufficient because an extension DLL may be exporting new classes as well as importing other classes from another extension DLL.

To deal with this problem, use a special pre-processor symbol that indicates you are building the DLL itself versus just using the DLL. For example, imagine two extension DLLs (A.DLL and B.DLL). They each export some classes in A.H and B.H, respectively. B.DLL uses the classes from A.DLL. The header files would look something like this:

// A.H
#ifdef A_IMPL
#define CLASS_DECL_A _declspec(dllexport)
#else
#define CLASS_DECL_A _declspec(dllimport)
#endif

class CLASS_DECL_A CExampleA : public CObject
{ ... class definition ... };

// B.H
#ifdef B_IMPL
#define CLASS_DECL_B _declspec(dllexport)
#else
#define CLASS_DECL_B _declspec(dllimport)
#endif

class CLASS_DECL_B CExampleB : public CExampleA
{ ... class definition .. };
When A.DLL is built, it is built with /D A_IMPL, and when B.DLL is built, it is built with /D B_IMPL. By using separate symbols for each DLL, you ensure that CExampleB is exported and CExampleA is imported when building B.DLL. CExampleA is exported when building A.DLL and imported when used by B.DLL or some other client. This type of layering cannot be done when using the built-in AFX_EXT_CLASS and _AFXEXT pre-processor symbols. The technique described above solves this problem in a manner not unlike the mechanism MFC itself uses when building its OLE, Database, and Network extension DLLs.
Всегда Ваш, PSP.
Re[4]: Экспорт/импорт DLL
От: iLLness  
Дата: 05.10.01 08:20
Оценка:
Здравствуйте PSP, Вы писали:

PSP>The DECLARE_DYNCREATE macro includes all the functionality of

PSP>DECLARE_DYNAMIC.

У меня просто классы serializable, поэтому использую DECLARE_SERIAL.

PSP>Кажется нашёл, что тебя спасёт, кусок из MSDN:


PSP> define CLASS_DECL_A _declspec(dllexport)


Спасибо огромное!!! Я в это же время сам понял что надо использовать _declspec(dllexport) :)
Илья Лощинин
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.