g++ - Поиск подходящих библиотек Windows для связи, чтобы скомпилировать библиотеку FANN
По разным причинам я пытался собрать библиотеку FANN самостоятельно. Я на Windows 10 с MinGW. Для простоты я собирался начать что-то вроде этого:
g++ mushroom.c -o shroom.exe -lm -I src\ -I src\include\ src\doublefann.c
(mushroom.c
включает в себя <stdio.h>
а также "fann.h"
.)
С использованием -I src\ -I src\include\ src\doublefann.c
позволил мне избавиться от различных неопределенных ошибок ссылок, возникающих из-за того, что заголовочные файлы не были найдены, но теперь он продолжает выдавать следующую неопределенную ссылку:
doublefann.c:(.text+0x4ee9): undefined reference to GetTickCount()
К вашему сведению, это появляется в fann.h (строка 54):
/* COMPAT_TIME REPLACEMENT */
#ifndef _WIN32
#include <sys/time.h>
#else /* _WIN32 */
#if !defined(_MSC_EXTENSIONS) && !defined(_INC_WINDOWS)
extern unsigned long __stdcall GetTickCount(void);
Короче говоря, это похоже на ошибку при связывании библиотек Windows, и я не знаю, как действовать, чтобы найти соответствующие ссылки.
Вот полный fann.h и полный doublefann.c
1 ответ
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ И ЗАМЕЧАНИЯ
РЕДАКТИРОВАТЬ: После того, как я пошел спать прошлой ночью, я усовершенствовал свой подход, чтобы вам не приходилось редактировать фактические исходные файлы FANN. (Кстати, мой оригинальный подход сработал, и вы можете посмотреть историю изменений, чтобы увидеть, что это было, если вам действительно все равно).
Во-первых, для всех, кто сталкивается с этим вопросом, я должен отметить, что использовать FANN таким образом не обязательно. Сайт предоставляет файлы cmake, а также решения Visual Studio, которые отлично работают.
В ЧЕМ ДЕЛО
Оглядываясь назад на вопрос, проблема очевидна, и я ненавижу себя за то, что не видел ее раньше, чем через много часов. Вы заметите, что все файлы в этой команде имеют *.c
расширение. Простите, что вы относитесь к вам как к новичку, но я не могу предположить, что вы что-то знаете, или я рискну дать неправильный ответ. *.c
каноническое расширение файла для исходных файлов на языке Си Набор инструментов gnu является довольно гибким программным обеспечением, и вы можете компилировать код на C с помощью g++
без ошибок большую часть времени. Но вы не должны, потому что вы получите эту ошибку. Так как ваш исходный файл, mushroom.c
, является исходным файлом C, вам будет достаточно скомпилировать код как C (в данном случае с gcc
не g++
). Если, однако, вы используете в своей программе такие вещи, как iostream
или же string
или классы или любой другой код C++, вы правы, чтобы скомпилировать его как C++ (условно вы бы изменили расширение тогда на *.cpp
для пояснения, но я не уверен, что GNU toolchain заботится). В этом случае всякий раз, когда вы хотите включить код C в вашу программу C++, обязательно оберните его в extern "C"{}
, так что компилятор знает, что соглашения о вызовах и метки являются стандартом C, который не всегда совпадает со стандартом C++. Это означает, что не только вызов кода C из C++ без extern "C"
рискует передать аргументы функциям неверным способом (хороший способ вызвать segfault), но способ, которым переменные и функции переименовываются при компиляции в сборку, различен для двух языков, поэтому вы получаете Undefined Reference
на этапе компоновки, но не на этапе компиляции. В этом случае не только doublefann.c
исходный файл C (который сам по себе прекрасно связывается), но также и библиотека, которая содержит объявление функции GetTickCount()
, В частности, вы ссылаетесь на %SYSTEMROOT%\System32\kernel32.dll
(обычно, но я считаю, что MinGW использует PATH_TO_MinGW\lib\lib32k.a
), который определяет, как программы могут взаимодействовать с операционной системой Windows на уровне машинного кода. __stdcall
Утилита определяется здесь, чтобы называть такие вещи, как GetTickCount()
из ОС, которые являются функциями сборки, в коде C. Потому что это в *.dll
, компилятор не может измениться __stdcall
в соответствии с соглашениями C++. Это связано с тем, что "dll
"означает"Динамически связанная библиотека". По сути, это означает, что эти файлы уже были скомпилированы в машинный код, когда была установлена Windows (или MinGW). Поэтому редактирование бессмысленно, потому что вам необходимо иметь глубокие рабочие знания кодов операций для каждый процессор x86_64, когда-либо созданный. Таким образом, вызов в C сделает все так, чтобы __stdcall
ожидает, но вызов в C++ требует extern "C"
или он искажает имена объявлений вашей функции и может вызвать ошибки во время выполнения.
ТЛ; др
FANN написан на C, C= / =C++, поэтому не ожидайте, что компилятор C++ всегда будет идеально компилировать код C.
Решение
Есть два способа решить эту проблему.
1
Если вы используете функции / библиотеки C++, измените имя вашего исходного кода на mushroom.cpp
(если хотите) и измените строку (везде, где это происходит в вашей программе)
#include "doublefann.c"
быть завернутым так:
extern "C"{
#include "doublefann.c"
}
Если вы прочитали fann.h, вы могли заметить строки:
#ifdef __cplusplus //line 65
extern "C"
{
#ifndef __cplusplus
} /* to fool automatic indention engines */
#endif
#endif /* __cplusplus */
Не волнуйтесь, они не конфликтуют. Честно говоря, я не уверен, что эти строки предназначены для достижения, но я уверен, что они знают, что они делают.
2
Если mushroom.c
на самом деле это просто чистый C, просто скомпилируйте с помощью:
gcc -o shroom.exe mushroom.c -lm -I src\ -I src\ -I src\include\ src\doublefann.c -Wall
и это должно работать. я добавил -Wall
потому что мне нравится, когда я могу сделать свой код абсолютно совершенным, не стесняйтесь оставлять это, он просто печатает все ваши предупреждения.