2016-03-20 2 views
0

Я пытаюсь загрузить общий объект (SensorTemp производный класс) во время выполнения с помощью API dlopen(). Когда я пытаюсь статическому случае указатель на соответствующий указатель на функцию, я получаюC++ static cast с .so загрузкой во время выполнения

LinkTest.cpp:26:48: error: invalid static_cast from type ‘void*’ to type ‘Sensor*()’ 
Sensor* mySensor = static_cast<Sensor *()>(mkr)(myHub, a, b, c, d, e); 

Вот соответствующий Sensor.h базовый конструктор класса:

class Sensor 
{ 
public: 
    Sensor(Hub& _pHub, const std::string& _name, const std::string& _type, const std::string& _logLevel, const std::string& _configInfo, const std::string& _location): m_pHub(&_pHub), m_name(_name), m_type(_type), m_logLevel(_logLevel), m_configInfo(_configInfo), m_location(_location) {} 

производный класс SensorTemp.h: (его CTOR называет базовый CTOR)

#include "Sensor.h" 

class SensorTemp : public Sensor 
{ 
public: 
    SensorTemp(Hub& _pHub, const std::string& _name, 
          const std::string& _type, 
          const std::string& _logLevel, 
          const std::string& _configInfo, 
          const std::string& _location); 
    ~SensorTemp() {} 
    void* Run(); 
private: 
    int m_lowTemp; 
    int m_highTemp; 
    int m_interval; 
}; 

extern "C" 
{ 
    SensorTemp* Create(Hub& _pHub, const std::string& _name, 
            const std::string& _type, 
            const std::string& _logLevel, 
            const std::string& _configInfo, 
            const std::string& _location) 
    { 
     return new SensorTemp(_pHub, _name, _type, _logLevel, _configInfo, _location); 
    } 

} 

#endif //__SENSORTEMP_H__ 

тест:

int main(int argc, char **argv) 
{ 
    Hub myHub; 
    string a = "A"; 
    string b = "B"; 
    string c = "C"; 
    string d = "D"; 
    string e = "E"; 
    string f = "F"; 
    void *hndl = dlopen("./libSensorTemp.so", RTLD_LAZY); 
    if(hndl == NULL) 
    { 
     std::cerr << dlerror() << std::endl; 
     exit(-1); 
    } 
    void *mkr = (Sensor*)dlsym(hndl, "Create"); 
    Sensor* mySensor = static_cast<Sensor *()>(mkr)(myHub, a, b, c, d, e); 
    mySensor->Run(); 

} 
+1

Посмотрите на [этот вопрос] (http://stackoverflow.com/questions/1096341/function-pointers-ca Укус-в-с). –

ответ

1

Со ссылкой на this question, здесь является упрощенным примером:

#include <dlfcn.h> 
#include <string> 

class Sensor; 
class Hub; 

extern "C" 
{ 
    Sensor* Create(Hub& _pHub 
     , const std::string& _name 
     , const std::string& _type 
     , const std::string& _logLevel 
     , const std::string& _configInfo 
     , const std::string& _location) 
    { 
     return nullptr; 
    } 
} 



int main(int argc, char **argv) 
{ 
    void *hndl = dlopen("./libSensorTemp.so", RTLD_LAZY); 
    if(hndl == NULL) { 
     exit(-1); 
    } 

    void *mkr = (Sensor*)dlsym(hndl, "Create"); 

    typedef Sensor*(*create_fn)(Hub& 
     , const std::string& 
     , const std::string& 
     , const std::string& 
     , const std::string& 
     , const std::string&); 

    create_fn creator = 0; 
    *reinterpret_cast<void**>(&creator) = mkr; 

    // .... 
} 
+0

Спасибо! Я прочитал ссылку, но не могу понять логику последних двух строк: почему the = 0? и почему reinterpreting как void **? не является целью преобразования указателя void в указатель функции? – susdu

+1

'= 0', поэтому мы имеем переменную указателя функции, инициализированную некоторым разумным значением. Причина 'void **' заключается в том, что вы не можете напрямую преобразовать указатель на указатель на объект. Однако указатель на указатель функции (т. Е. 'Create_fn *') ** является ** указателем на объект. Так что 'void **'. Следовательно, мы можем конвертировать между ними. Итак, с '* reinterpret_cast (& creator)' мы переинтерпретируем создателя как 'void *', и присваивание действительно. –

+0

Проблема теперь в './libSensorTemp.so: undefined symbol: _ZTI6Sensor'. Когда производный класс CTOR вызывает базовый класс, имя базового CTOR искажается и не может его разрешить. – susdu

1

Ваш приведение к указателю на функцию неправильное. Ваш код должен быть:

void *mkr = (void *)dlsym(hndl, "Create"); // only the address matters here 
Sensor* mySensor = static_cast<Sensor *(*)(Hub&, const std::string&, const std::string&, 
    const std::string&, const std::string&, const std::string&)>(mkr)(myHub, a, b, c, d, e); 
mySensor->Run(); 

Потому что вы хотите, чтобы бросить mkr в указатель на функцию, принимающую один Hub ссылку и 5 string ссылки и возвращающей указатель на Sensor

+0

'LinkTest.cpp: 27: 69: error: invalid static_cast от типа 'void *' для ввода 'Sensor * (*) (Hub &, const string &, const string &, const string &, const string &, const string &) {aka Sensor * (*) (& концентратор, Const станд :: basic_string &, Const станд :: basic_string &, Const станд :: basic_string &, Const станд :: basic_string &, Const станд :: basic_string &)}» Const std :: string &, const std :: string &, const std :: string &)> (mkr) (myHub, a, b, c, d, e); ' – susdu

+0

Какой компилятор вы используете? Я не могу воспроизвести ошибку. Я тестировал свой код с помощью MSVC2008 express ... –

+0

Я использую gcc, но если это компилятор depedent, это, вероятно, не самый лучший подход – susdu