Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Экспорт класса из DLL  (Прочитано 21903 раз)
0 Пользователей и 1 Гость смотрят эту тему.
tosha_82
Интересующийся

ru
Offline Offline

« : 15-05-2011 05:44 » 

Добрый день!
Я экспортирую класс из DLL как написано в книгах, но главный проект никак не хочет собираться, не находит тело функций в lib файле, может это примудрости C++ Builder ? Экспорт работает только на Visual C++ ?
Вот код DLL :
Заголовочный файл:
Код:
#ifndef MYSQL_DLL_H
#define MYSQL_DLL_H
//---------------------------------------------------------------------------
#include <mysql.h>
//---------------------------------------------------------------------------
#ifdef  SQLDLL_EXPORT
#define SQLDLL_EXPORT __declspec(dllexport)
#else
#define SQLDLL_EXPORT __declspec(dllimport)
#endif
//---------------------------------------------------------------------------
struct SQLDLL_EXPORT STLOGIN
{
AnsiString host;
AnsiString user;
AnsiString password;
AnsiString DB;
int clientflag;
int port;
};
//---------------------------------------------------------------------------
class SQLDLL_EXPORT TSQL
{
private:
   MYSQL *sql_proc;
   MYSQL_RES *Res;
   MYSQL_ROW Row;
   bool ConnectedMySQL;
public:
TSQL();
~TSQL();

void __fastcall ConnectMySQL(STLOGIN *stLogin);
void __fastcall DisconnectMySQL();
bool __fastcall GetStatusMySQL();
};
//---------------------------------------------------------------------------
#endif

Файл cpp:
Код:
#include <vcl.h>
#include <windows.h>
#include "MySqlDll.h"
#pragma hdrstop
//---------------------------------------------------------------------------
TSQL::TSQL()
{
//constructor
}
//---------------------------------------------------------------------------
TSQL::~TSQL()
{
//destructor
}
//---------------------------------------------------------------------------

void __fastcall TSQL::ConnectMySQL(STLOGIN *stLogin)
{
sql_proc = mysql_init(sql_proc);
sql_proc = mysql_real_connect(sql_proc,stLogin->host.c_str(),stLogin->user.c_str(),
  stLogin->password.c_str(),stLogin->DB.c_str(),
  stLogin->port,NULL,stLogin->clientflag);
if(!sql_proc) ShowMessage("Не доступен сервер MySQL Server!");
else ConnectedMySQL = true;
}
//---------------------------------------------------------------------------

void __fastcall TSQL::DisconnectMySQL()
{
if(sql_proc) mysql_close(sql_proc);
sql_proc=NULL;
}
//---------------------------------------------------------------------------

bool __fastcall TSQL::GetStatusMySQL()
{
return ConnectedMySQL;
}
//---------------------------------------------------------------------------
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}
//---------------------------------------------------------------------------

DLL файл собирается отлично. После копирую файл MySqlDll.h, MySqlDll.dll и MySqlDll.lib в папку с проектом exe
Подключаю все это дело в проект:
В Main.h подключаю #include "MySqlDll.h"
В Main.cpp создаю объекты
Код:
#include <vcl.h>
#pragma hdrstop

#include "Main.h"
#include "About.h"
//---------------------------------------------------------------------------
#pragma resource "*.dfm"
#pragma comment(lib,"MySqlDll.lib")
//---------------------------------------------------------------------------
TMainForm *MainForm;
TSQL *SQLInterface;
STLOGIN *stLogin;
bool startMDI=false;
//---------------------------------------------------------------------------

__fastcall TMainForm::TMainForm(TComponent *Owner)
: TForm(Owner)
{
   SQLInterface = new TSQL();
   stLogin = new STLOGIN();
}
//---------------------------------------------------------------------------

Ну и при сборке проекта получаю:
[ILINK32 Error] Error: Unresolved external 'TSQL::~TSQL()' referenced from E:\PROJECTS\DEBUG\MAIN.OBJ
[ILINK32 Error] Error: Unresolved external 'TSQL::TSQL()' referenced from E:\PROJECTS\DEBUG\MAIN.OBJ
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 15-05-2011 12:00 » 

tosha_82, а где в cpp-файле определено SQLDLL_EXPORT до включения заголовочного файла? Сборка DLL идёт точно с dllexport, а не dllimport?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
tosha_82
Интересующийся

ru
Offline Offline

« Ответ #2 : 15-05-2011 12:05 » 

Цитата
до включения заголовочного файла?
Никогда о таком не слышал, чтобы __declspec(dllexport) еще и в cpp определяли. Это для чего?
Описание в h файле есть  и он подключается в обоих проектах, иначе бы компилятор тогда ошибку выдавал.
Можно по-подробнее?
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 15-05-2011 15:44 » 

tosha_82, хм... Что означают по-твоему вот эти строчки?
Код: (C++)
#ifdef  SQLDLL_EXPORT
#define SQLDLL_EXPORT __declspec(dllexport)
#else
#define SQLDLL_EXPORT __declspec(dllimport)
#endif
Как это по-твоему работает?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
tosha_82
Интересующийся

ru
Offline Offline

« Ответ #4 : 15-05-2011 15:47 » 

Ну если не было определено SQLDLL_EXPORT, то оно определяется компилятором как __declspec(dllexport), в противном случае __declspec(dllimport)
Т.е. в exe модуле перед h файлом необходимо добавить
#define SQLDLL_EXPORT      ?
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 15-05-2011 17:06 » 

tosha_82, и что получится?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
tosha_82
Интересующийся

ru
Offline Offline

« Ответ #6 : 16-05-2011 01:07 » 

Ничего не получилось  Здесь была моя ладья...

в exe проекте добавил в cpp, поидее компилятор должен определять теперь как dllimport
Код:
#include <vcl.h>
#pragma hdrstop

#define  SQLDLL_EXPORT
#include "Main.h"
#include "About.h"
//---------------------------------------------------------------------------
#pragma resource "*.dfm"
#pragma comment(lib,"MySqlDll.lib")
//---------------------------------------------------------------------------
TMainForm *MainForm;
TSQL *SQLInterface;
STLOGIN *stLogin;
bool startMDI=false;
//---------------------------------------------------------------------------

__fastcall TMainForm::TMainForm(TComponent *Owner)
: TForm(Owner)
{
   SQLInterface = new TSQL();
   stLogin = new STLOGIN();
}
//---------------------------------------------------------------------------

но линковщик все равно выдает:
Цитата
[ILINK32 Error] Error: Unresolved external 'TSQL::~TSQL()' referenced from E:\PROJECTS\DEBUG\MAIN.OBJ
[ILINK32 Error] Error: Unresolved external 'TSQL::TSQL()' referenced from E:\PROJECTS\DEBUG\MAIN.OBJ
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 16-05-2011 04:03 » 

tosha_82, слабо понял, что ты делаешь. У меня есть лишь предположение, что ты путаешь экспорт и импорт. Зачем тебе экспорт в exe?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
tosha_82
Интересующийся

ru
Offline Offline

« Ответ #8 : 16-05-2011 04:23 » 

Не, там идет импорт, изначально правильно было, не надо в cpp ничего объявлять. Нашел косяк
Заменил в заголовочном файл строку
Код:
#ifdef SQLDLL_EXPORT
на
Код:
#ifndef SQLDLL_EXPORT

Все заработало, спасибо  Улыбаюсь
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #9 : 16-05-2011 05:18 » 

tosha_82, а зачем ты в посте №6 объявляешь MainForm? Ты же Main.h подключаешь - там должно быть объявление.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 16-05-2011 05:22 » 

Сдаётся мне (но на 100% не уверен), что переопределение макроса SQLDLL_EXPORT может игнорироваться препроцессором. По крайней мере, почему бы для подстановки __declspec не объявить ещё один макрос, SQLDLL_API, например, чтобы избавиться от двусмысленности?
Записан
tosha_82
Интересующийся

ru
Offline Offline

« Ответ #11 : 16-05-2011 08:10 » 

Цитата
osha_82, а зачем ты в посте №6 объявляешь MainForm? Ты же Main.h подключаешь - там должно быть объявление.
MainForm объявлен в  Main.h как extern,  это нормально, чтобы в других cpp файлах того же проекта использовать MainForm. Если объявить его явно в h, то компилятор начнет ругаться, что дубликаты присутствуют в *.obj файлах.
А вообще не я объявлял  Улыбаюсь  Это builder по умолчанию так проект создает
У меня: Embarcadero RAD Studio XE 2010

Цитата
Сдаётся мне (но на 100% не уверен), что переопределение макроса SQLDLL_EXPORT может игнорироваться препроцессором. По крайней мере, почему бы для подстановки __declspec не объявить ещё один макрос, SQLDLL_API, например, чтобы избавиться от двусмысленности?

Я пробовал и так и так, работает одинаково на ура, но для наглядности да, согласен, я уже поменял SQLDLL_EXPORT на _SQLDLL_  Улыбаюсь
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines