Экспорт класса, динамика
От: Sheridan Россия  
Дата: 16.09.10 18:53
Оценка:
Приветствую!
Уважаемые, подскажите пожалуйста, как кроссплатформенно экспортировать из библиотеки класс и динамически его импортировать потом в приложении.
avalon 1.0rc3 rev 306, zlib 1.2.3 (17.12.2009 01:06:14 MSK +03:00)(Qt 4.6.0)
Matrix has you...
Re: Телепаты-то в отпуске!
От: Erop Россия  
Дата: 16.09.10 19:20
Оценка:
Здравствуйте, Sheridan, Вы писали:

S>Уважаемые, подскажите пожалуйста, как кроссплатформенно экспортировать из библиотеки класс и динамически его импортировать потом в приложении.


Совсем кроспслатформенно никак. Но если ты расскажешь подробности, то многое может оказаться возможным...

Например, если код, который экспортирует класс и код, который его импортирует, находятся на одной машине и работают под управлением одной и той же платформы, то часто можно сделать абстрактный класс, содержащий, быть может только pure virtual методы и inline методы, без статических данных в них.
Главное -- никаких данных (полей) в интерфейсе!!!
Теперь в экспортирующем модуле заводим функцию, которая возвращает указатель на такой интерфейс. При этом из этого интерфейса выводим класс, в котором всё реализуем и указатель на такой класс мы и выдаём наружу...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
уроки телепатии
Re[2]: Телепаты-то в отпуске!
От: Sheridan Россия  
Дата: 16.09.10 20:02
Оценка:
Приветствую, Erop, вы писали:

E> Совсем кроспслатформенно никак. Но если ты расскажешь подробности, то многое может оказаться возможным...

ок )

E> Например, если код, который экспортирует класс и код, который его импортирует, находятся на одной машине и работают под управлением одной и той же платформы,

Конечно.

E> то часто можно сделать абстрактный класс, содержащий, быть может только pure virtual методы и inline методы, без статических данных в них.

E> Главное -- никаких данных (полей) в интерфейсе!!!
E> Теперь в экспортирующем модуле заводим функцию, которая возвращает указатель на такой интерфейс. При этом из этого интерфейса выводим класс, в котором всё реализуем и указатель на такой класс мы и выдаём наружу...
class Exporting
{
public:
  virtual int func() = 0;
  virtual float other() = 0;
};

class My : public Exporting
{
public:
  int funct() { return m_str.size(); }
  float other() { return 4.4; } 
private:
  std::string m_str;
};

extern "C"
{
  Exporting * getClass();
}
Exporting * getClass()
{
  return new My();
}

Так?
avalon 1.0rc3 rev 306, zlib 1.2.3 (17.12.2009 01:06:14 MSK +03:00)(Qt 4.6.0)
Matrix has you...
Re: Экспорт класса, динамика
От: Mamut Швеция http://dmitriid.com
Дата: 16.09.10 20:04
Оценка:
S>Приветствую!
S>Уважаемые, подскажите пожалуйста, как кроссплатформенно экспортировать из библиотеки класс и динамически его импортировать потом в приложении.

по идее есть тут: http://pocoproject.org/, Poco::SharedLibrary и Poco::ClassLoader

Но как с ними работать — хз


dmitriid.comGitHubLinkedIn
Re[2]: Ну или вот
От: Mamut Швеция http://dmitriid.com
Дата: 16.09.10 20:06
Оценка: 1 (1)
Здравствуйте, Mamut, Вы писали:

S>>Приветствую!

S>>Уважаемые, подскажите пожалуйста, как кроссплатформенно экспортировать из библиотеки класс и динамически его импортировать потом в приложении.

M>по идее есть тут: http://pocoproject.org/, Poco::SharedLibrary и Poco::ClassLoader


M>Но как с ними работать — хз


есть еще тут: http://www.codeproject.com/KB/library/dynobj.aspx


dmitriid.comGitHubLinkedIn
Re[3]: Ну или вот
От: Sheridan Россия  
Дата: 16.09.10 20:22
Оценка:
Приветствую, Mamut, вы писали:

M> Здравствуйте, Mamut, Вы писали:


M> S>>Приветствую!

M> S>>Уважаемые, подскажите пожалуйста, как кроссплатформенно экспортировать из библиотеки класс и динамически его импортировать потом в приложении.

M> M>по идее есть тут: http://pocoproject.org/, Poco::SharedLibrary и Poco::ClassLoader

M> есть еще тут: http://www.codeproject.com/KB/library/dynobj.aspx

Спасибо конечно, довольно красиво все.... Но заради этого цеплять в зависимости еще одну библиотеку я еще не готов...
avalon 1.0rc3 rev 306, zlib 1.2.3 (17.12.2009 01:06:14 MSK +03:00)(Qt 4.6.0)
Matrix has you...
Re[3]: Телепаты-то в отпуске!
От: Erop Россия  
Дата: 17.09.10 04:44
Оценка:
Здравствуйте, Sheridan, Вы писали:


S>Так?


Почти.
Что за класс? Это какой-то интерфейс большой, ну, скажем, интерфейс приложения, или это какой-то объект?
Сколько экземпляров этого класса может быть в наличии?

Просто надо как-то решить вопросы владения.
Во-первых, нехорошо, что с вызывающей стороны могут удалить этот твой экземпляр. Сервер может быть не готов, кроме того, клиент это может сделать как-то не так.

Намного надёжнее деструктор сделать protected, а в интерфейс добавить метод virtual void Destroy() = 0, который тоже реализовать в My. Ну там в виде delete this, например. Или COW замутить, если надо. Обычно при построениии таких систем экспортированных объектов (скажем в COM, например) имеют какой-то интерфейс, который как раз отвечает за владение и прочие токости, а из него выводят уже все остальные.

Но если нужно экспортировать интерфейс синглетона, то можно так не заморачиваться а просто завести статический объект и возвращать из той самой функции его адрес.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Экспорт класса, динамика
От: Pavel Dvorkin Россия  
Дата: 17.09.10 04:50
Оценка: 8 (1)
Здравствуйте, Sheridan, Вы писали:

S>Приветствую!

S>Уважаемые, подскажите пожалуйста, как кроссплатформенно экспортировать из библиотеки класс и динамически его импортировать потом в приложении.

Если вопрос поставлен именно так — ответ : "никак", потому что понятия экспорта и даже библиотеки не кроссплатформенны.
With best regards
Pavel Dvorkin
Re[3]: Телепаты-то в отпуске!
От: Centaur Россия  
Дата: 17.09.10 04:59
Оценка:
Здравствуйте, Sheridan, Вы писали:

S>class Exporting
S>{
S>public:
S>  virtual int func() = 0;
S>  virtual float other() = 0;
S>};


Это поломается при использовании между компиляторами с разным размером и/или представлением int и float или разной конвенцией вызовов по умолчанию. На Windows я бы переписал так:

class Exporting
{
public:
  virtual INT __stdcall func() = 0;
  virtual DOUBLE __stdcall other() = 0;
};


Поскольку такого же вида определения используются в Windows SDK, компилятор, который не обеспечит совместимость, не сможет компилировать виндовые приложения.

Ну и если в реализующем классе используются какие-нибудь классы (std::string, контейнеры, etc.), в интерфейсе их показывать нельзя. Можно дать доступ к внутренностям (s.c_str(), s.data(), &*s.begin(), &s[0]), с учётом времени жизни соответствующих ссылок и указателей.

S>class My : public Exporting
S>{
S>public:
S>  int funct() { return m_str.size(); }
S>  float other() { return 4.4; } 
S>private:
S>  std::string m_str;
S>};

S>extern "C"
S>{
S>  Exporting * getClass();
S>}
S>Exporting * getClass()
S>{
S>  return new My();
S>}


Здесь ещё нужен механизм удаления. Либо extern "C" void deleteObject(Exporting *), либо метод в интерфейсе. Идиоматично будет сразу навернуть в интерфейсе интрузивный подсчёт ссылок через AddRef() / Release() и выполнять delete this из Release(), когда счётчик ссылок падает до нуля.

С клиентской стороны можно добавить умный указатель, инкапсулирующий вызовы AddRef/Release (в случае подсчёта ссылок) или Clone/deleteObject (в случае обычного владения).
Re[4]: Ну или вот
От: Smooky Россия  
Дата: 17.09.10 06:40
Оценка:
Здравствуйте, Sheridan, Вы писали:

S>Приветствую, Mamut, вы писали:


M>> M>по идее есть тут: http://pocoproject.org/, Poco::SharedLibrary и Poco::ClassLoader


S>Спасибо конечно, довольно красиво все.... Но заради этого цеплять в зависимости еще одну библиотеку я еще не готов...


Не, это всё правильно, а вот библа Poco реально классная! (просто хотел заметить)
Только Путин, и никого кроме Путина! О Великий и Могучий Путин — царь на веки веков, навсегда!
Смотрю только Соловьева и Михеева, для меня это самые авторитетные эксперты.
КРЫМ НАШ! СКОРО И ВСЯ УКРАИНА БУДЕТ НАШЕЙ!
Re[3]: Телепаты-то в отпуске!
От: Sni4ok  
Дата: 17.09.10 07:18
Оценка:
Здравствуйте, Sheridan, Вы писали:

S>
S>class Exporting
S>{
S>public:
S>  virtual int func() = 0;
S>  virtual float other() = 0;
S>};
S>


незабудь добавить виртуальный деструктор, а грузить потом это можно так:

#ifdef WIN32
typedef HINSTANCE engine_handle;
#define ENGINE_HANDLE_FREE(handle) FreeLibrary(handle)
#else
#include <dlfcn.h>
typedef void* engine_handle;
#define ENGINE_HANDLE_FREE(handle) dlclose(handle)
#endif

struct free_library
{
    engine_handle handle;
    free_library(engine_handle handle) : handle(handle){
    }
    void operator()(){
        ENGINE_HANDLE_FREE(handle);
    }
};

Exporting* load_engine(std::string engine, boost::function<void()>& free_lib){
#ifdef  WIN32
    engine += ".dll";
    engine_handle handle =LoadLibrary(engine.c_str());
#else
    engine = "./lib" + engine + ".so";
    engine_handle handle = dlopen(engine.c_str(), RTLD_LAZY);
#endif
    if (!handle)
        throw std::runtime_error((boost::format("load library \"%s\" error") % engine).str());

    typedef Exporting* (getClass)();
    getClass *api = 
#ifdef WIN32
    (getClass*)GetProcAddress(handle, "getClass");
#else
    (getClass*)dlsym(handle, "getClass");
#endif
    if(!api){
        ENGINE_HANDLE_FREE(handle);
        throw std::runtime_error((boost::format("not found getClass() method in library %s") % engine).str());
    }
    free_lib = free_library(handle);
    return api();
}
Re[4]: Ну или вот
От: Mamut Швеция http://dmitriid.com
Дата: 17.09.10 08:14
Оценка:
M>> S>>Приветствую!
M>> S>>Уважаемые, подскажите пожалуйста, как кроссплатформенно экспортировать из библиотеки класс и динамически его импортировать потом в приложении.

M>> M>по идее есть тут: http://pocoproject.org/, Poco::SharedLibrary и Poco::ClassLoader

M>> есть еще тут: http://www.codeproject.com/KB/library/dynobj.aspx

S>Спасибо конечно, довольно красиво все.... Но заради этого цеплять в зависимости еще одну библиотеку я еще не готов...


А другого выхода нет Потому что стандартизированного способа это сделать в С++ не предусмотрено.

Кстати, вспомнилось еще, что в Qt есть система плагинов, которая занимается тем же, кстати.


dmitriid.comGitHubLinkedIn
Re[5]: Ну или вот
От: Sheridan Россия  
Дата: 17.09.10 14:06
Оценка:
Приветствую, Mamut, вы писали:

M> А другого выхода нет Потому что стандартизированного способа это сделать в С++ не предусмотрено.

Это я уже понял )

M> Кстати, вспомнилось еще, что в Qt есть система плагинов, которая занимается тем же, кстати.

В курсе, применял уже. Только вот сильно жирно будет куте сюда...
avalon 1.0rc3 rev 306, zlib 1.2.3 (17.12.2009 01:06:14 MSK +03:00)(Qt 4.6.0)
Matrix has you...
Re[4]: Телепаты-то в отпуске!
От: Sheridan Россия  
Дата: 17.09.10 14:06
Оценка:
Приветствую, Erop, вы писали:

E> S>Так?

E> Почти.
E> Что за класс? Это какой-то интерфейс большой, ну, скажем, интерфейс приложения, или это какой-то объект?
Таких либ пока что пара.
1) читает / пише конфиг и дает доступ к параметрм
2) работа с сетью — серверный\кдиентский сокет...

E> Сколько экземпляров этого класса может быть в наличии?

Вполне возможно что больше одного

E> Просто надо как-то решить вопросы владения.

E> Во-первых, нехорошо, что с вызывающей стороны могут удалить этот твой экземпляр. Сервер может быть не готов, кроме того, клиент это может сделать как-то не так.
Так, стоп... У нас есть 2 приложения, в каждом по паре указателей на экземпляры класса. Насколько я понимаю — между собой приложения никак пересечься не могут — следовательно разговор идет только о возможных проблемах внутри одного приложения?

E> Намного надёжнее деструктор сделать protected, а в интерфейс добавить метод virtual void Destroy() = 0, который тоже реализовать в My. Ну там в виде delete this, например. Или COW замутить, если надо. Обычно при построениии таких систем экспортированных объектов (скажем в COM, например) имеют какой-то интерфейс, который как раз отвечает за владение и прочие токости, а из него выводят уже все остальные.

Хорошая идея, спасибо, подумаю.

E> Но если нужно экспортировать интерфейс синглетона, то можно так не заморачиваться а просто завести статический объект и возвращать из той самой функции его адрес.

Гм... надо подумать...
avalon 1.0rc3 rev 306, zlib 1.2.3 (17.12.2009 01:06:14 MSK +03:00)(Qt 4.6.0)
Matrix has you...
Re[5]: Телепаты-то в отпуске!
От: Erop Россия  
Дата: 17.09.10 14:19
Оценка:
Здравствуйте, Sheridan, Вы писали:

S>Так, стоп... У нас есть 2 приложения, в каждом по паре указателей на экземпляры класса. Насколько я понимаю — между собой приложения никак пересечься не могут — следовательно разговор идет только о возможных проблемах внутри одного приложения?


Да, речь идёт о каждом приложении независимо. Во всяком случае в современной винде и линуксе.

Но если учесть то, что ты написал, то возникает вопрос. А точно ли тебе нужен С++ интерфейс? Может достатончо будет если завернуть его в С'шный API?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Телепаты-то в отпуске!
От: Sheridan Россия  
Дата: 17.09.10 14:36
Оценка:
Приветствую, Erop, вы писали:

E> Но если учесть то, что ты написал, то возникает вопрос. А точно ли тебе нужен С++ интерфейс? Может достатончо будет если завернуть его в С'шный API?


Ну какбы я так уже вроде и сделал...
Слепил пару экспортных С функций, одна возвращает указатель на абстрактный класс, вторая удаляет этот класс...
Или проблема именно в том, что я потом работаю с классом?
avalon 1.0rc3 rev 306, zlib 1.2.3 (17.12.2009 01:06:14 MSK +03:00)(Qt 4.6.0)
Matrix has you...
Re[7]: Телепаты-то в отпуске!
От: dmitry_npi Россия  
Дата: 17.09.10 14:42
Оценка:
Здравствуйте, Sheridan, Вы писали:

Посмотрите на Windows GDI+. (хоть она и не кроссплатформенная Там dll экспортирует сишные функции наподобие

SomeObject_DoSomething(HANDLE obj, INT param1, FLOAT param2);


А затем поверх всего этого существует легкая header-only С++ обертка.
Атмосферная музыка — www.aventuel.net
Re[4]: Телепаты-то в отпуске!
От: _b_l_  
Дата: 18.09.10 10:20
Оценка:
Здравствуйте, Centaur, Вы писали:

C>Здравствуйте, Sheridan, Вы писали:


C>
S>>class Exporting
S>>{
S>>public:
S>>  virtual int func() = 0;
S>>  virtual float other() = 0;
S>>};
C>


C>Это поломается при использовании между компиляторами с разным размером и/или представлением int и float или разной конвенцией вызовов по умолчанию. На Windows я бы переписал так:


На Windows для этих целей лучше использовать COM.

C>Поскольку такого же вида определения используются в Windows SDK, компилятор, который не обеспечит совместимость, не сможет компилировать виндовые приложения.


C>Ну и если в реализующем классе используются какие-нибудь классы (std::string, контейнеры, etc.), в интерфейсе их показывать нельзя. Можно дать доступ к внутренностям (s.c_str(), s.data(), &*s.begin(), &s[0]), с учётом времени жизни соответствующих ссылок и указателей.


С другой стороны, если всё собирать одним компилятором с одинаковыми настройками, то все эти сложности ни к чему.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.