Здравствуйте, Tujh, Вы писали:
// dev_functions.hpp
typedef boost::uint32_t ulong;
...
// Надо дать структуре имя, а не через имя typedef оперделять оператор
typedef struct index
{
ulong p_int;
ulong p_dec;
operator double();
} index;
...
std::string crc16(const void *ptr, const size_t length);
Здравствуйте.
Столкнулся с непонятным для меня поведением компилятора GCC 4.1.1 (arm-linux-g++ если быть точным)
Описание достаточно общирное, так как вопрос мне не понятен, постараюсь объяснить подробно.
Проект — динамическая библиотека (.dll/.so) под M$Win(x86) и Linux (ARM) по опросу некоторого типа устройств. Согласно протокола обмена числа с плавающей точкой хранятся в устройстве в виде пары целых чисел, соответственно захотелось удобств и приделал оператор приведения к double. Выглядело это первоначально так:
// dev_functions.hpp
typedef boost::uint32_t ulong;
...
typedef struct
{
ulong p_int;
ulong p_dec;
operator double();
} index;
...
std::string crc16(const void *ptr, const size_t length);
// dev_functions.cpp
//
index::operator double()
{
double l_int = static_cast<double> (p_int);
double l_dec = static_cast<double> (p_dec);
l_dec /= 100000000.0;
return (l_int + l_dec);
}
//-------------------------------------------------------------------------
//
std::string crc16(const void *ptr, const size_t length)
{
[skip]
}
//-------------------------------------------------------------------------
// currents.cpp
...
l_str.assign(response, 22, 8);
index l_vol;
memcpy(&l_vol, l_str.c_str(), sizeof(index));
m_de_map[de_low_address::dev::current::volume]->set_value(
static_cast<double> (l_vol),
quality_good,
l_ptime,
false
);
...
ни чего особо хитрого, структура, с перегруженным оператором приведения заполняется простым копированием участка памяти.
Под MSVC2005 (VC8.0) все прекрасно собралось в .dll и так же отлично работало.
При сборке с arm-linux-g++ ни каких особых проблем не было, но вот при работе программы, использующей эту .so возникли проблемы, точнее сообщение '...unknown symbol indexcvd...' с последующим "падением" приложения. Место локализовалось быстро, нет реализации оператора приведения в double.
Путем "бубнения" был найден следующий код, который работает в GCC
// dev_functions.hpp
typedef boost::uint32_t ulong;
...
typedef struct
{
ulong p_int;
ulong p_dec;
operator double()
{
double l_int = static_cast<double> (p_int);
double l_dec = static_cast<double> (p_dec);
l_dec /= 100000000.0;
return (l_int + l_dec);
}
} index;
...
std::string crc16(const void *ptr, const size_t length);
// dev_functions.cpp
//
std::string crc16(const void *ptr, const size_t length)
{
[skip]
}
//-------------------------------------------------------------------------
// currents.cpp
...
l_str.assign(response, 22, 8);
index l_vol;
memcpy(&l_vol, l_str.c_str(), sizeof(index));
m_de_map[de_low_address::dev::current::volume]->set_value(
static_cast<double> (l_vol),
quality_good,
l_ptime,
false
);
...
в таком варианте все работает. Хотя по сути, изменений — только перенос кода из .срр в .hpp
Вариант с тем, что в makefile не был включен нужный .о или .срр файл исключен, так как функция crc16 (приведена в листинге) из этого файла прекрасно работала, а значит компилировалась и линковалась.
Может кто сталкивался с таким поведением gcc или просто знает ответ, просветите пожалуйста, почему реализация, прописанная в .cpp игнорировалась.
Заранее благодарю.