Приветствую!
Уважаемые, подскажите пожалуйста, как кроссплатформенно экспортировать из библиотеки класс и динамически его импортировать потом в приложении.
Здравствуйте, Sheridan, Вы писали:
S>Уважаемые, подскажите пожалуйста, как кроссплатформенно экспортировать из библиотеки класс и динамически его импортировать потом в приложении.
Совсем кроспслатформенно никак. Но если ты расскажешь подробности, то многое может оказаться возможным...
Например, если код, который экспортирует класс и код, который его импортирует, находятся на одной машине и работают под управлением одной и той же платформы, то часто можно сделать абстрактный класс, содержащий, быть может только pure virtual методы и inline методы, без статических данных в них.
Главное -- никаких данных (полей) в интерфейсе!!!
Теперь в экспортирующем модуле заводим функцию, которая возвращает указатель на такой интерфейс. При этом из этого интерфейса выводим класс, в котором всё реализуем и указатель на такой класс мы и выдаём наружу...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Приветствую, 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();
}
S>Приветствую! S>Уважаемые, подскажите пожалуйста, как кроссплатформенно экспортировать из библиотеки класс и динамически его импортировать потом в приложении.
Здравствуйте, Mamut, Вы писали:
S>>Приветствую! S>>Уважаемые, подскажите пожалуйста, как кроссплатформенно экспортировать из библиотеки класс и динамически его импортировать потом в приложении.
M>по идее есть тут: http://pocoproject.org/, Poco::SharedLibrary и Poco::ClassLoader
M>Но как с ними работать — хз
Приветствую, 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
Спасибо конечно, довольно красиво все.... Но заради этого цеплять в зависимости еще одну библиотеку я еще не готов...
Почти.
Что за класс? Это какой-то интерфейс большой, ну, скажем, интерфейс приложения, или это какой-то объект?
Сколько экземпляров этого класса может быть в наличии?
Просто надо как-то решить вопросы владения.
Во-первых, нехорошо, что с вызывающей стороны могут удалить этот твой экземпляр. Сервер может быть не готов, кроме того, клиент это может сделать как-то не так.
Намного надёжнее деструктор сделать protected, а в интерфейс добавить метод virtual void Destroy() = 0, который тоже реализовать в My. Ну там в виде delete this, например. Или COW замутить, если надо. Обычно при построениии таких систем экспортированных объектов (скажем в COM, например) имеют какой-то интерфейс, который как раз отвечает за владение и прочие токости, а из него выводят уже все остальные.
Но если нужно экспортировать интерфейс синглетона, то можно так не заморачиваться а просто завести статический объект и возвращать из той самой функции его адрес.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Sheridan, Вы писали:
S>Приветствую! 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]), с учётом времени жизни соответствующих ссылок и указателей.
Здесь ещё нужен механизм удаления. Либо extern "C" void deleteObject(Exporting *), либо метод в интерфейсе. Идиоматично будет сразу навернуть в интерфейсе интрузивный подсчёт ссылок через AddRef() / Release() и выполнять delete this из Release(), когда счётчик ссылок падает до нуля.
С клиентской стороны можно добавить умный указатель, инкапсулирующий вызовы AddRef/Release (в случае подсчёта ссылок) или Clone/deleteObject (в случае обычного владения).
Здравствуйте, Sheridan, Вы писали:
S>Приветствую, Mamut, вы писали:
M>> M>по идее есть тут: http://pocoproject.org/, Poco::SharedLibrary и Poco::ClassLoader
S>Спасибо конечно, довольно красиво все.... Но заради этого цеплять в зависимости еще одну библиотеку я еще не готов...
Не, это всё правильно, а вот библа Poco реально классная! (просто хотел заметить)
Только Путин, и никого кроме Путина! О Великий и Могучий Путин — царь на веки веков, навсегда!
Смотрю только Соловьева и Михеева, для меня это самые авторитетные эксперты.
КРЫМ НАШ! СКОРО И ВСЯ УКРАИНА БУДЕТ НАШЕЙ!
M>> S>>Приветствую! M>> S>>Уважаемые, подскажите пожалуйста, как кроссплатформенно экспортировать из библиотеки класс и динамически его импортировать потом в приложении.
M>> M>по идее есть тут: http://pocoproject.org/, Poco::SharedLibrary и Poco::ClassLoader M>> есть еще тут: http://www.codeproject.com/KB/library/dynobj.aspx
S>Спасибо конечно, довольно красиво все.... Но заради этого цеплять в зависимости еще одну библиотеку я еще не готов...
А другого выхода нет Потому что стандартизированного способа это сделать в С++ не предусмотрено.
Кстати, вспомнилось еще, что в Qt есть система плагинов, которая занимается тем же, кстати.
Приветствую, Mamut, вы писали:
M> А другого выхода нет Потому что стандартизированного способа это сделать в С++ не предусмотрено.
Это я уже понял )
M> Кстати, вспомнилось еще, что в Qt есть система плагинов, которая занимается тем же, кстати.
В курсе, применял уже. Только вот сильно жирно будет куте сюда...
Приветствую, Erop, вы писали:
E> S>Так? E> Почти. E> Что за класс? Это какой-то интерфейс большой, ну, скажем, интерфейс приложения, или это какой-то объект?
Таких либ пока что пара.
1) читает / пише конфиг и дает доступ к параметрм
2) работа с сетью — серверный\кдиентский сокет...
E> Сколько экземпляров этого класса может быть в наличии?
Вполне возможно что больше одного
E> Просто надо как-то решить вопросы владения. E> Во-первых, нехорошо, что с вызывающей стороны могут удалить этот твой экземпляр. Сервер может быть не готов, кроме того, клиент это может сделать как-то не так.
Так, стоп... У нас есть 2 приложения, в каждом по паре указателей на экземпляры класса. Насколько я понимаю — между собой приложения никак пересечься не могут — следовательно разговор идет только о возможных проблемах внутри одного приложения?
E> Намного надёжнее деструктор сделать protected, а в интерфейс добавить метод virtual void Destroy() = 0, который тоже реализовать в My. Ну там в виде delete this, например. Или COW замутить, если надо. Обычно при построениии таких систем экспортированных объектов (скажем в COM, например) имеют какой-то интерфейс, который как раз отвечает за владение и прочие токости, а из него выводят уже все остальные.
Хорошая идея, спасибо, подумаю.
E> Но если нужно экспортировать интерфейс синглетона, то можно так не заморачиваться а просто завести статический объект и возвращать из той самой функции его адрес.
Гм... надо подумать...
Здравствуйте, Sheridan, Вы писали:
S>Так, стоп... У нас есть 2 приложения, в каждом по паре указателей на экземпляры класса. Насколько я понимаю — между собой приложения никак пересечься не могут — следовательно разговор идет только о возможных проблемах внутри одного приложения?
Да, речь идёт о каждом приложении независимо. Во всяком случае в современной винде и линуксе.
Но если учесть то, что ты написал, то возникает вопрос. А точно ли тебе нужен С++ интерфейс? Может достатончо будет если завернуть его в С'шный API?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Приветствую, Erop, вы писали:
E> Но если учесть то, что ты написал, то возникает вопрос. А точно ли тебе нужен С++ интерфейс? Может достатончо будет если завернуть его в С'шный API?
Ну какбы я так уже вроде и сделал...
Слепил пару экспортных С функций, одна возвращает указатель на абстрактный класс, вторая удаляет этот класс...
Или проблема именно в том, что я потом работаю с классом?
C>Это поломается при использовании между компиляторами с разным размером и/или представлением int и float или разной конвенцией вызовов по умолчанию. На Windows я бы переписал так:
На Windows для этих целей лучше использовать COM.
C>Поскольку такого же вида определения используются в Windows SDK, компилятор, который не обеспечит совместимость, не сможет компилировать виндовые приложения.
C>Ну и если в реализующем классе используются какие-нибудь классы (std::string, контейнеры, etc.), в интерфейсе их показывать нельзя. Можно дать доступ к внутренностям (s.c_str(), s.data(), &*s.begin(), &s[0]), с учётом времени жизни соответствующих ссылок и указателей.
С другой стороны, если всё собирать одним компилятором с одинаковыми настройками, то все эти сложности ни к чему.