#c #cmake #shared-libraries #poco-libraries
#c #cmake #общие библиотеки #poco-библиотеки
Вопрос:
Я пытаюсь создать простую систему плагинов. У меня есть три класса в библиотеке:
// AbstractPlugin.h
//
// This is used both by the class library and by the application.
#ifndef AbstractPlugin_INCLUDED
#define AbstractPlugin_INCLUDED
#include <string>
class AbstractPlugin
{
public:
AbstractPlugin();
virtual ~AbstractPlugin();
virtual std::string name() const = 0;
};
#endif // AbstractPlugin.h
// AbstractPlugin.cpp
//
// This is used both by the class library and by the application.
#include "AbstractPlugin.h"
AbstractPlugin::AbstractPlugin()
{
}
AbstractPlugin::~AbstractPlugin()
{
}
// PluginLibrary.cpp
#include "AbstractPlugin.h"
#include "Poco/ClassLibrary.h"
#include <iostream>
#include <string>
class PluginA: public AbstractPlugin
{
public:
std::string name() const
{
return "PluginA";
}
};
class PluginB: public AbstractPlugin
{
public:
std::string name() const
{
return "PluginB";
}
};
POCO_BEGIN_MANIFEST(AbstractPlugin)
POCO_EXPORT_CLASS(PluginA)
POCO_EXPORT_CLASS(PluginB)
POCO_END_MANIFEST
// optional set up and clean up functions
void pocoInitializeLibrary()
{
std::cout << "PluginLibrary initializing" << std::endl;
}
void pocoUninitializeLibrary()
{
std::cout << "PluginLibrary uninitializing" << std::endl;
}
Это мой main.cpp файл. Я пытался загрузить библиотеку, даже используя относительные пути и не используя префикс «lib».
// main.cpp
#include "Poco/ClassLoader.h"
#include "Poco/Manifest.h"
#include "AbstractPlugin.h"
#include <iostream>
#include <Poco/SharedLibrary.h>
using Poco::SharedLibrary;
typedef Poco::ClassLoader<AbstractPlugin> PluginLoader;
typedef Poco::Manifest<AbstractPlugin> PluginManifest;
int main(int argc, char** argv)
{
PluginLoader loader;
std::string libName("/home/sstoenescu/Work/toys/pocoClassLoaderExample/libPluginLibrary");
libName = Poco::SharedLibrary::suffix(); // append .dll or .so
loader.loadLibrary(libName);
PluginLoader::Iterator it(loader.begin());
PluginLoader::Iterator end(loader.end());
for (; it != end; it)
{
std::cout << "lib path: " << it->first << std::endl;
PluginManifest::Iterator itMan(it->second->begin());
PluginManifest::Iterator endMan(it->second->end());
for (; itMan != endMan; itMan)
{
std::cout << itMan->name() << std::endl;
}
}
AbstractPlugin* pPluginA = loader.create("PluginA");
AbstractPlugin* pPluginB = loader.create("PluginB");
std::cout << pPluginA->name() << std::endl;
std::cout << pPluginB->name() << std::endl;
loader.classFor("PluginA").autoDelete(pPluginA);
delete pPluginB;
loader.unloadLibrary(libName);
return 0;
}
Это то, что я получаю:
завершение вызывается после создания экземпляра ‘Poco::LibraryLoadException’, что(): Невозможно загрузить библиотеку Прервано (ядро сброшено)
Я не могу понять, что не так. Мой CMakeLists.txt файл выглядит следующим образом:
cmake_minimum_required(VERSION 2.8.3)
project(tutocpp14)
#set(Poco_DIR "/usr/local/lib/cmake/Poco/")
set(Poco_DIR "/usr/local/lib/")
set(Poco_INCLUDE_DIRS "/usr/include/Poco/")
find_package(Poco REQUIRED COMPONENTS Foundation Net XML Util) # add other components here
# check c 11 / c 0x
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c 11 " COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c 0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "-std=c 11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "-std=c 0x")
else()
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C 11 support. Please use a different C compiler.")
endif()
include_directories( ${Poco_INCLUDE_DIRS})
add_library(PluginLibrary SHARED src/PluginLibrary.cpp)
add_executable(publisher src/main.cpp)
target_link_libraries(publisher ${Poco_LIBRARIES})
Комментарии:
1. Не уверен насчет Poco, но обычно библиотеки плагинов создаются с использованием ключевого слова MODULE для
add_library
, а не для ОБЩЕГО .2. Поместите блок try … catch в main и catch
Poco::Exception
. Это должно дать вам больше информации о том, что пошло не так, напримерtry { /* your PluginLoader code */ } catch (Poco::Exceptionamp; exc) { std::cout << exc.displayText(): }
3. Спасибо! Это показало мне, что я сделал что-то не так с AbstractPlugin. Если я помещу AbstractPlugin в PluginLibrary.cpp это работает. Возможно, причина этого в том, что в Poco нет манифеста в AbstractLibrary.cpp
Ответ №1:
Решением было поместить класс AbstractPlugin в тот же исходный файл, где находятся инструкции manifest (PluginLibrary.cpp), который является файлом, который фактически создан как библиотека .so.