Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [C++] Доступ к объекту, созданному в dll 
:(
    Опции темы
scroollocker
  Дата 23.8.2013, 19:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.{--}.



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 17.9.2010

Репутация: нет
Всего: нет



Всем привет.

Случилась такая ситуация у меня, непонятная для меня... Вообщем прошу помощи. 

Есть некоторый класс - интерфейс:
Код

class IDb {
    public:
        virtual ~IDb() {}
        virtual int getData() = 0;    
        virtual void clearData() = 0;
};


В dll создаю его наследника, 

Код

class clDb : public IDb {
    private:
        int *_data;
        
    public:
                clDb() {
                      _data = new int(50);
                }
        virtual ~clDb() {
                          clearData();
                 }
        virtual int getData(){
                          return *_data
                }    
        virtual void clearData() {
                      if (_data) delete _data;
                      _data = NULL;
                }            
};


Затем в той же dll создаю 2е функции, одна будет возвращать созданный в dll объект. Другая уничтожать его.

Код

IDb* makeObject() {
    clDb *myUpDb = new clDb();
    return myUpDb;         
}

void freeObject(IDb *pDb) {
     if (pDb) {
        try {
            delete pDb;         
        }
        catch(...) {}
     }
}


А уже в программе, которая загружает dll, используя интерфейс IDb, хочу пользоваться методами. Но, по какой-то причине, объект возвращается указывающий на какой то мусор... 

Вот код главной программы:
Код

typedef IDb* (*pGetObjectFunc)(void);
typedef void (*pFreeObjectFunc)(IDb *);

int main(int argc, char *argv[])
{
     char *cDllPath = new char[50];
     sprintf(cDllPath,"dll_test.dll");
          
     HMODULE hPluginDBDll = LoadLibraryA(cDllPath);
     if (!hPluginDBDll) {
        return 0;           
     }    
     
     pGetObjectFunc getFunc;
     pFreeObjectFunc freeFunc;
     
     getFunc   = (pGetObjectFunc)GetProcAddress(hPluginDBDll,"makeObject");
     freeFunc  = (pFreeObjectFunc)GetProcAddress(hPluginDBDll,"freeObject");
     
     IDb *myObject;
     myObject = getFunc();
     cout << "Data = " << myObject->getData() << endl;
     
     myObject->clearData();
     
     freeFunc(myObject);
     
     FreeLibrary(hPluginDBDll);
     
     return 0;
}


Что я делаю не так? чего я не знаю? подскажите пожалуйста

*UPD
- очепятался

Это сообщение отредактировал(а) scroollocker - 23.8.2013, 22:51
PM MAIL WWW ICQ Jabber   Вверх
feodorv
Дата 23.8.2013, 20:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(scroollocker @  23.8.2013,  20:43 Найти цитируемый пост)
указывающий на какой то мусор

Гм. Что-то странное Вы делаете с указателями:
Цитата(scroollocker @  23.8.2013,  20:43 Найти цитируемый пост)
        int *_data;

это понятно;
Цитата(scroollocker @  23.8.2013,  20:43 Найти цитируемый пост)
                      *_data = new int(50);

Вот это не понятно. По адресу _data размещается другой адрес, указывающий на int со значением 50... Должно быть, имелось в виду:
Код

_data = new int(50);




--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
scroollocker
Дата 23.8.2013, 22:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.{--}.



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 17.9.2010

Репутация: нет
Всего: нет



feodorv

Да все верно, это я опечатка здесь, т.к. в программе конструкция немного помассивней. Здесь хотел показать то, что в dll в классе выделяется  память под объекты. А в основной программе, данные просматриваются. 

Это сообщение отредактировал(а) scroollocker - 23.8.2013, 22:57
PM MAIL WWW ICQ Jabber   Вверх
borisbn
Дата 24.8.2013, 06:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Dll и exe сделаны одним компилятором? С одними и теми же настройками типа вызова и упаковкой структур? GetProcAddress возвращает не NULL?


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
scroollocker
Дата 24.8.2013, 13:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.{--}.



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 17.9.2010

Репутация: нет
Всего: нет



borisbn
да, оба собраны в minGW, настройки одни и те же. 

Цитата

GetProcAddress возвращает не NULL? 


Да, не NULL.  

Здесь пример уж слишком прост, в программе, над которой работаю, там есть методы, которые динамически работают со списками. Добавляют удаляют, получают данные. 
PM MAIL WWW ICQ Jabber   Вверх
feodorv
Дата 24.8.2013, 16:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(scroollocker @  24.8.2013,  14:39 Найти цитируемый пост)
Здесь пример уж слишком прост

Но он работает?
Может, дело как раз в том, что
Цитата(scroollocker @  23.8.2013,  23:53 Найти цитируемый пост)
в программе конструкция немного помассивней




--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
scroollocker
Дата 24.8.2013, 19:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.{--}.



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 17.9.2010

Репутация: нет
Всего: нет



feodorv

пример этот тоже проверял, тоже не работает. Даже не происходит вызов конструктора класса. 

Никак не могу понять причину. Может кто нибудь посоветует другой способ, чтобы был один интерфейс для взаимодействия с объектами, созданными в dll. Если я изменю методы, добавлю поля, чтобы не было необходимости изменять\перекомпилировать код основной программы.
PM MAIL WWW ICQ Jabber   Вверх
Alexeis
Дата 25.8.2013, 12:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



 Одинаковая версия компилятора для Dll и для Exe совсем не обязательно. Достаточно использовать COM совместимые интерфейсы. У меня студия прекрасно работает с объектами созданными в билдере и наоборот. При передаче объектов, просто нужно соблюдать несколько простых правил. 
1) В каком модуле выделил, в том и освободил. 
2) Передавать в методы объекта можно либо POD типы (с указанным выравниванием) или интерфейсы.
3) Не рекомендуется передавать тип enum, так как его размер зависит от настроек компилятора.
4) Исключения не должны покидать модуль. Если функция может сгенерить исключение, то его лучше поймать и вернуть кодом ошибки.
5) Внимательно работать со строками. Объект std::string или аналогичный не должен покидать границу модуля. Тут же со строками. Если обмениваться строками типа whar_t*/char* можно использовать функцию SysAllocString, она использует внешний менеджер памяти. Тоже самое послабление можно сделать для POD типов если объединить менеджеры памяти (общий менеджер памяти в отдельной Dll).
6) Не создавать для интерфейсов конструкторы и деструкторы.  




--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
feodorv
Дата 25.8.2013, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(scroollocker @  24.8.2013,  20:26 Найти цитируемый пост)
пример этот тоже проверял, тоже не работает

Проверил на MS Visual C++ 6.0, работает)))

Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  cl.ZIP 1,45 Kb


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
scroollocker
Дата 25.8.2013, 19:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.{--}.



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 17.9.2010

Репутация: нет
Всего: нет



Код заработал. Обновил компилятор на новую версию. НО. 
Программа все равно вылетает на этом месте:
Код

freeFunc(myObject); 


Оказалось, если объявленное в dll 
Код

void freeObject(IDb *pDb) {
     if (pDb) {
        try {
            delete pDb;         
        }
        catch(...) {}
     }
}

изменить на 
Код

void freeObject(clDb *pDb) {
     if (pDb) {
        try {
            delete pDb;         
        }
        catch(...) {}
     }
}

программа работает нормально. 

feodorv
да спасибо, обновил компилятор, тоже уже стало работать. Попробуйте вызвать freeFunc(myObject); На этом месте у меня вылетает теперь =(


Alexeis

Спасибо за развернутый ответ, возьму на заметку приведенные вами правила. Буду переделывать класс, в соответствии с ними. 
PM MAIL WWW ICQ Jabber   Вверх
borisbn
Дата 25.8.2013, 22:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Alexeis
7) Нельзя в интерфейсе создавать перегруженные функции

2 ТС:
Я для удаления объекта добавляю в него метод destroy, который в наследнике делает delete this; IMHO удобнее



--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
scroollocker
Дата 29.8.2013, 18:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.{--}.



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 17.9.2010

Репутация: нет
Всего: нет



Вроде все шло хорошо, на одинаковых компиляторах было все супер... Решил попробовать на C++ Builder, и началось.... Не хочет понимать объект через интерфейс.. В связи с этим, хочу уточнить пару моментов:

Цитата

5) Внимательно работать со строками. Объект std::string или аналогичный не должен покидать границу модуля. 


Получается нельзя в созданные в dll объект ни отдавать не принимать std::string. Можно об этом пункте поподробней. Т.к. у меня существует класс - Хранилище. 
В него можно добавлять, удалять, изменять хранящиеся там объекты. А вот эти объекты как раз и хранят в себе std::string. Вопрос, как мне подогнать классы, чтобы можно было хранить\получать\изменять эту структуру и чтобы интерфейс был кросскомпиляторным?


Интерфейс работы с БД:
Код

class IDb {
    public:
        virtual ~IDb() {}
        virtual int getCount() = 0;    
        virtual void init() = 0;
        virtual void clearData() = 0;
        virtual bool load() = 0;
        virtual bool save() = 0;
        virtual bool deleteItem(int) = 0;
        virtual void setPath(std::string ) = 0;
};

class IUpDataDb : public IDb {
    public:
        virtual ~IUpDataDb() {}    
        virtual void add(UP_DATA) = 0;
        virtual UP_DATA get(int) = 0;        
        virtual bool insert(int,UP_DATA) = 0;
        virtual bool replaceItem(int,UP_DATA) = 0;                    
};


сама структура UP_DATA имеет вид:

Код

struct UP_DATA {
    int id;
    std::string host;
    std::string uname;
    std::string pass;
};

PM MAIL WWW ICQ Jabber   Вверх
Alexeis
Дата 29.8.2013, 23:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



Цитата(scroollocker @  29.8.2013,  19:45 Найти цитируемый пост)
Получается нельзя в созданные в dll объект ни отдавать не принимать std::string. Можно об этом пункте поподробней.

   Нельзя передавать такие объекты в качестве параметров интерфейсов. Тем более структуры содержащие такие объекты. А еще тут сразу видно деструктор интерфейса. Интерфейс не должен иметь конструкторов и деструкторов, тем более виртуальных. Можно использовать char* char[] в таких структурах. Но в любом случае желательно чтобы память выделялась с одной стороны. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0954 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.