Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > DLL+Release — Unresolved external...


Автор: kometa_triatlon 24.11.2005, 23:20
Есть проект, использующий неявное подключение ДЛЛ.
В класс dll запихнул нужные мне функции, приложение получает результат работы через вспомогательную функцию. Вроде все ничего, но как обычно, в дебаге работает нормально, в версии release не билдится smile
Получаю следующее:

Код

lab1 error LNK2019: unresolved external symbol "__declspec(dllimport) class CObArray * __cdecl Run(class ATL::CStringT<char,class StrTraitMFC<char,class ATL::ChTraitsCRT<char> > > *,int)" (__imp_?Run@@YAPAVCObArray@@PAV?$CStringT@DV?$StrTraitMFC@DV?$ChTraitsCRT@D@ATL@@@@@ATL@@H@Z) referenced in function "public: void __thiscall CMyDlg::OnToolsRun(void)" (?OnToolsRun@CMyDlg@@QAEXXZ)


Некоторые части кода вот:
Объявление импортируемой функции:
Код

__declspec (dllimport) CObArray* Run(CString*, int );


В dll:
Код

#include "resource.h"        // main symbols
#include "afxcoll.h"
#include "VarItem.h"


// CanalyserApp
// See analyser.cpp for the implementation of this class
//
enum SUBPROG_TYPE { FUNCTION, PROCEDURE }; 

class CanalyserApp : public CWinApp
{
public:
    CanalyserApp();

// Overrides
public:
    virtual BOOL InitInstance();

    DECLARE_MESSAGE_MAP()
private:
    CString* m_arrStrCode;
    int m_iLineCount;
    CObArray m_arrVarList;
public:
    CObArray* AnalyseCode(CString* strCode, int iLineCount);

private:
    void GetVarsFromInit(CString strVars, VARSTATE state, int iLine, char lpszType[10],  CString strSubProgName = PRIMARY_PROG);
    bool ConformFormat(CString strLine, CString strFormat);
    void GetVarsFromParameters(CString strLine, VARSTATE state, int iLine, CString strSubprogName);
    CString GetSubprogName(SUBPROG_TYPE type, CString);
};

 __declspec (dllexport) CObArray* Run(CString* strCode, int iLineCount);


Код

__declspec (dllexport) CObArray* Run(CString* strCode, int iLineCount)
{
    return theApp.AnalyseCode(strCode, iLineCount);
}

Проблема конечно более чем распространенная, но в поиске не нашел... Может мне как-то переписать код?

Автор: AlexPro 25.11.2005, 05:51
Если склероз мне не изменяет, в свое время у меня у меня тоже было нечто подобное, сейчас использую def-файл для экспортируемых функций - работает на ура. smile

Автор: nikf 25.11.2005, 07:46
дело не в коде. линкер видит объявленную функцию в h файле, но не видит ее реализации... где-то потерялись твоя dll... или забыл подсоединить библиотеку импорта .lib. просто повнимательнее посмотри. dll должна быть в папке куда компилишь релиз екзешника.
Добавлено @ 07:48
или в релизие твоему екзешнику попадается старая версия dll не содержащая данной функции

Автор: kometa_triatlon 26.11.2005, 00:33
А ведь точно, я в дебаге настроил директории, указал путь к библиотеке импорта, думал, что для релиза эти настройки сохранятся, оказалось все не так радужно...
Спасибо nikf за трезвую идею smile

Автор: En_t_end 26.11.2005, 07:47
kometa_triatlon
Если я тебя правильно понял, то советую в таком случае все либы подключать прямо, а не в настройке проекта... #pragma comment(lib,"some.lib")

Автор: kometa_triatlon 26.11.2005, 17:14
En_t_end
Ок, но у меня output directory для проекта dll-ки указана не как обычно, а на уровень выше. Как это можно указать в коде?

Автор: AlexPro 27.11.2005, 04:46
Цитата(kometa_triatlon @ 26.11.2005, 00:33)
я в дебаге настроил директории, указал путь к библиотеке импорта, думал, что для релиза эти настройки сохранятся, оказалось все не так радужно

Очень даже радужно smile. Достаточно в свойствах проекта выбрать All configurations - и изменяемые тобой настройки будут иметь место во всех твоих восьми с половиной сборках (включая Debug и Release).

Автор: DeadSoul 27.11.2005, 13:40
kometa_triatlon, была такая бага. Долго пиииииииииииииип. У тебя неправильно(а вернее по разному) указаны настройки проекта в dll и exe. Нужно выставить одинаковыми:
- Project -> Properties -> General -> Character Set
- Project -> Properties -> C\C++ -> Language -> Treat wchar_t as build-in type

Автор: kometa_triatlon 30.11.2005, 00:07
Вопрос в догонку: как экспортировать из библиотеки только один метод класса:
Я сделал так: объявил в библиотеке экспортируемую функцию
Код

 __declspec (dllexport) CPtrArray* Run(CString* strCode, int iLineCount);

но она только вызывает метод класса:
Код

__declspec (dllexport) CPtrArray* Run(CString* strCode, int iLineCount)
{
    return theApp.AnalyseCode(strCode, iLineCount);
}


Почитал МСДН, переделал так:
Код

class CanalyserApp : public CWinApp
{
public:
    CanalyserApp();

// Overrides
public:
    virtual BOOL InitInstance();

    DECLARE_MESSAGE_MAP()
private:
    CString* m_arrStrCode;
    int m_iLineCount;
    CPtrArray m_arrVarList;
public:


    AFX_EXT_CLASS CPtrArray* AnalyseCode(CString* strCode, int iLineCount);



private:
    void GetVarsFromInit(CString strVars, VARSTATE state, int iLine, char lpszType[10],  CString strSubProgName = PRIMARY_PROG);
    bool ConformFormat(CString strLine, CString strFormat);
    void GetVarsFromParameters(CString strLine, VARSTATE state, int iLine, CString strSubprogName);
    CString GetSubprogName(SUBPROG_TYPE type, CString);
};


AFX_EXT_CLASS CPtrArray* CanalyserApp::AnalyseCode(CString* strCode, int iLineCount)
{ ....

Но не пойму теперь как обьявить этот метод для клиента, раньше было просто:

Код

__declspec (dllimport) CPtrArray* Run(CString*, int );

Если оставить как есть, получаю unresolved, заменяю __declspec (dllimport) на AFX_EXT_CLASS то же самое smile
Что-то не нашел в МСДН такого...

Автор: bel_nikita 30.11.2005, 00:14
kometa_triatlon
Цитата
Вроде все ничего, но как обычно, в дебаге работает нормально, в версии release не билдится
Для релиз ЕХЕ должны быть релиз DLL и также для дебаг EXE должен быть DLL.

Что в препроцессоре прописано?
Чтобы экспортировать MFC класы из DLL - она должна быть MFC extension DLL.

Автор: kometa_triatlon 30.11.2005, 00:47
bel_nikita
Ту проблему я уже решил

Я так понял, если я экспортирую только один метод класса, все равно DLL должна быть расширенной?

Автор: bel_nikita 30.11.2005, 01:00
Цитата(kometa_triatlon @ 29.11.2005, 23:47)
Я так понял, если я экспортирую только один метод класса, все равно DLL должна быть расширенной?

Что значит экспортировать метод класса??? Можно либо весь класс экспортировать, либо неклассовые методы, либо переменные.

Автор: Earnest 30.11.2005, 09:58
bel_nikita ты абсолютно не прав...
Можно экспортировать как все методы класса, так и только выбранные.
В первом случае спецификация экспорта-импорта ставится в определении класса, во- втором - только в определении метода, как в примере у kometa_triatlon.

Цитата(kometa_triatlon @ 30.11.2005, 00:47)
Я так понял, если я экспортирую только один метод класса, все равно DLL должна быть расширенной

Нет, не в этом дело. Просто когда визард создает extension DLL, он добавляет символ препроцессора _AFXEXT, а этот символ нужен для правильной интерпретации символов AFX_EXT_CLASS и т.д. Т.е., если есть _AFXEXT, то AFX_EXT_CLASS == declspec(dllimport), в противном случае - export. Можешь сам таких символов сочинить для каждой своей DLL, не важно, extension или нет.

Автор: bel_nikita 30.11.2005, 10:40
Точно. Век живи - век учись smile Только еще конструктор с собой цеплять нужно, ну экпортировать т.е.

Автор: Earnest 30.11.2005, 18:43
Цитата(bel_nikita @ 30.11.2005, 10:40)
Только еще конструктор с собой цеплять нужно, ну экпортировать т.е.

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

Спасибо тебе за репу.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)