У меня есть проект, который использует систему сборки autotools для создания статической библиотеки. Я хочу протестировать эту библиотеку, создав небольшую тестовую программу, которая ссылается на нее.
Тестовая программа создается в IDE code::blocks. Пути, содержащие заголовки, были добавлены в каталоги поиска, а также добавлена включенная библиотека.
Когда я компилирую свою тестовую программу, я получаю следующую ошибку:
obj/Debug/main.o: In function `givens':
<snip> undefined reference to `xhypot(double, double)'
Однако xhypot — это глобальная функция, объявленная во включенном заголовке в real.h
как:
nr_double_t xhypot (const nr_double_t, const nr_double_t);
и определено в сопутствующем файле real.cpp
.
nr_double_t xhypot (const nr_double_t a, const nr_double_t b) {
nr_double_t c = fabs (a);
nr_double_t d = fabs (b);
if (c > d) {
nr_double_t e = d / c;
return c * sqrt (1 + e * e);
}
else if (d == 0)
return 0;
else {
nr_double_t e = c / d;
return d * sqrt (1 + e * e);
}
}
Тип nr_double_t определен в config.h как:
/* The global type of double representation. */
#define nr_double_t double
Где происходит оскорбительный вызов xhypot
, так это в статической вспомогательной функции для класса шаблона, например:
static nr_double_t
givens (nr_double_t a, nr_double_t b, nr_double_t& c, nr_double_t& s) {
nr_double_t z = xhypot (a, b);
c = a / z;
s = b / z;
return z;
}
Однако xhypot
также вызывается в других нестатических функциях-членах класса с точно таким же синтаксисом (то есть xhypot(double,double)
, и если я заменю строку nr_double_t z = xhypot (a, b);
в этом статическом методе на строку nr_double_t z = 0.0;
, ошибка исчезнет.
Вот вся моя тестовая программа:
#include "config.h"
#include "m_trsolver.h"
int main (int argc, char ** argv)
{
char infile[] = "test.net";
m_trsolver the_m_trsolver;;
return 0;
}
И полный лог сборки:
g++ -Wall -DHAVE_CONFIG_H -g -I../qucs/qucs-core -I../qucs/qucs-core/src -I../qucs/qucs-core/src/components -I../qucs/qucs-core/src/components/devices -I../qucs/qucs-core/src/components/digital -I../qucs/qucs-core/src/components/verilog -I../qucs/qucs-core/src/components/microstrip -I../qucs/qucs-core/src/converter -I../qucs/qucs-core/src/m-interface -I../qucs/qucs-core/src/math -c /home/s0237326/src/qucs_m_interface_test/main.cpp -o obj/Debug/main.o
/home/s0237326/src/qucs_m_interface_test/main.cpp: In function ‘int main(int, char**)’:
/home/s0237326/src/qucs_m_interface_test/main.cpp:10: warning: unused variable ‘infile’
g++ -L../qucs/qucs-core -L../qucs/qucs-core/src -L../qucs/qucs-core/src/components -L../qucs/qucs-core/src/components/devices -L../qucs/qucs-core/src/components/digital -L../qucs/qucs-core/src/components/verilog -L../qucs/qucs-core/src/components/microstrip -L../qucs/qucs-core/src/converter -L../qucs/qucs-core/src/m-interface -L../qucs/qucs-core/src/math -o bin/Debug/qucs_m_interface_test obj/Debug/main.o ../qucs/qucs-core/src/libqucsatorfull.a
obj/Debug/main.o: In function `givens':
/home/s0237326/src/qucs_m_interface_test/../qucs/qucs-core/src/eqnsys.cpp:1341: undefined reference to `xhypot(double, double)'
obj/Debug/main.o: In function `main':
/home/s0237326/src/qucs_m_interface_test/main.cpp:11: undefined reference to `m_trsolver::m_trsolver()'
/home/s0237326/src/qucs_m_interface_test/main.cpp:13: undefined reference to `m_trsolver::~m_trsolver()'
collect2: ld returned 1 exit status
Process terminated with status 1 (0 minutes, 0 seconds)
3 errors, 1 warnings
Я использую code::blocks 10.05 в Scientific Linux 6.1 с gcc 4.4.6 и передаю -DHAVE_CONFIG_H, так как есть много
#if HAVE_CONFIG_H
# include <config.h>
#endif
В исходниках config.h
генерируется autoconf. Я также должен добавить, что код отлично компилируется при сборке в виде программы. Я извлек часть кода этой программы (все, кроме одного файла), чтобы поместить ее в эту статическую библиотеку.
Класс шаблона распределен по двум файлам, eqnsys.h
и eqnsys.cpp
. Я знаю, что это не лучшая практика, вероятно, это было сделано, так как он довольно большой. Это не мой код. eqnsys.cpp
включен в нижней части eqnsys.h
( #include "eqnsys.cpp"
). Статическая вспомогательная функция определена в eqnsys.cpp
. real.h
обозначается #include
ed сверху eqnsys.cpp
, но не eqnsys.h
, если это имеет значение. Добавьте следующее в начало eqnsys.cpp
:
template class eqnsys<nr_complex_t>;
template class eqnsys<nr_double_t>;
Принудительное создание экземпляра не решает проблему. Если я изменю данную функцию как функцию-член вместо статической вспомогательной функции, ошибка исчезнет. Это путь, по которому я мог бы пойти, но каков реальный корень проблемы, чтобы я мог избежать этого в будущем?
nr_double_t xhypot (const nr_double_t, const nr_double_t);
— это просто объявление в C++, а#define nr_double_t double
— это определение препроцессора. Однако компоновщик жалуется наm_trsolver
, а не наnr_double_t
. - person Luchian Grigore   schedule 24.05.2013xhypot
объявляется какnr_double_t xhypot (const nr_double_t, const nr_double_t);
, а типnr_double_t
определяется вconfig.h
какdouble
. Компоновщик жалуется на отсутствиеm_trsolver
, но первая ошибка связана сxhypot(double, double)
. Я не знаю, связаны ли они. Я отредактирую, чтобы внести пару исправлений. - person crobar   schedule 25.05.2013xhypot
, которая определена в других источниках и работает в другом месте в том же классе шаблона, почему? В этом ответе это не объясняется, я прочитал много других вопросов о переполнении стека, но не видел такой же проблемы. - person crobar   schedule 28.05.2013xhypot
объявлено в файлеreal.h
и определено вreal.cpp
, это глобальная функция. Он вызывается в других функциях-членах класса-шаблона с тем же синтаксисом, что и в этой статической функции-члене, то естьxhypot(double,double)
. Если я заменю строкуnr_double_t z = xhypot (a, b);
в статической функции-члене наnr_double_t z = 0.0
, ошибка исчезнет.xhypot
не является функцией-членом класса шаблона. - person crobar   schedule 28.05.2013