Я успешно загрузил плагин C ++ с помощью пользовательского класса загрузчика плагинов. Каждый плагин имеет внешнюю функцию "C" create_instance, которая возвращает новый экземпляр, используя "new".
Плагин - это абстрактный класс с несколькими не виртуальными функциями и несколькими защищенными переменными (одной из них является std :: vector refList).
Класс plugin_loader успешно загружает и даже вызывает виртуальный метод в загруженном классе (а именно: «std :: string plugin :: getName ()».
Основная функция создает экземпляр "хоста", который содержит вектор умных указателей с подсчетом ссылок refptr для класса "плагин". Затем main создает экземпляр plugin_loader, который фактически выполняет dlopen / dlsym, и создает экземпляр refptr, передавая ему create_instance (). Наконец, он передает созданный refptr обратно в функцию хоста addPlugin. host :: addPlugin успешно вызывает несколько функций в переданном экземпляре плагина и, наконец, добавляет его в вектор >.
Затем основная функция подписывается на несколько событий Apple и вызывает RunApplicationEventLoop (). Обратный вызов события декодирует результат, а затем вызывает функцию в host, host :: sendToPlugin, которая идентифицирует плагин, для которого предназначено событие, и затем вызывает обработчик в плагине. В этот момент все перестает работать.
host :: sendToPlugin считывает результат и определяет плагин, на который отправляется событие.
Я использую чрезвычайно простой плагин, созданный как плагин отладки, который возвращает статические значения для каждой не пустой функции.
Любой вызов любой виртуальной функции в плагине в векторе вызывает исключение плохого доступа. Я попытался заменить refptrs обычными указателями, а также boost :: shared_ptrs, и я получаю одно и то же исключение. Я знаю, что экземпляр плагина действителен, так как я могу исследовать экземпляр в отладчике Xcode и даже просматривать элементы в refList плагина.
Я думаю, что это может быть проблема с многопоточностью, потому что плагины были созданы в главном потоке, в то время как обратный вызов работает в отдельном потоке. Основной поток, судя по обратному следу, когда программа сталкивается с ошибкой, но я не знаю реализацию Apple RunApplicationEventLoop, поэтому я не могу быть уверен.
Есть идеи, почему это происходит?
class plugin
{
public:
virtual std::string getName();
protected:
std::vector<std::string> refList;
};
и класс pluginLoader:
template<typename T> class pluginLoader
{
public: pluginLoader(std::string path);
// initializes private mPath string with path to dylib
bool open();
// opens the dylib and looks up the createInstance function. Returns true if successful, false otherwise
T * create_instance();
// Returns a new instance of T, NULL if unsuccessful
};
class host
{
public:
addPlugin(int id, plugin * plug);
sendToPlugin(); // this is the problem method
static host * me;
private:
std::vector<plugin *> plugins; // or vector<shared_ptr<plugin> > or vector<refptr<plugin> >
};
код события яблока из host.cpp;
host * host::me;
pascal OSErr HandleSpeechDoneAppleEvent(const AppleEvent *theAEevt, AppleEvent *reply, SRefCon refcon) {
// this is all boilerplate taken straight from an apple sample except for the host::me->ae_callback line
OSErr status = 0;
Result result = 0;
// get the result
if (!status) {
host::me->ae_callback(result);
}
return status;
}
void host::ae_callback(Result result) {
OSErr err;
// again, boilerplate apple code
// grab information from result
if (!err)
sendToPlugin();
}
void host::sendToPlugin() {
// calling *any* method in plugin results in failure regardless of what I do
}
РЕДАКТИРОВАТЬ: Это выполняется на OSX 10.5.8, и я использую GCC 4.0 с Xcode. Это , а не , предназначенное для кроссплатформенного приложения.
РЕДАКТИРОВАТЬ: Чтобы было ясно, плагин работает до тех пор, пока предоставленный Apple цикл событий не вызовет мою функцию обратного вызова. Когда функция обратного вызова вызывает обратно в хост, когда все перестает работать. Это моя проблема, все остальное до этого момента работает.