По разным причинам я пытался собрать 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
РЕДАКТИРОВАТЬ: После того, как я пошел спать прошлой ночью, я усовершенствовал свой подход, чтобы вам не приходилось редактировать фактические исходные файлы FANN. (Кстати, мой оригинальный подход сработал, и вы можете посмотреть историю изменений, чтобы увидеть, что это было, если вам действительно все равно).
Во-первых, для всех, кто сталкивается с этим вопросом, я должен отметить, что использовать FANN таким образом не обязательно. Сайт предоставляет файлы cmake, а также решения Visual Studio, которые отлично работают.
Оглядываясь назад на вопрос, проблема очевидна, и я ненавижу себя за то, что не видел ее раньше, чем через много часов. Вы заметите, что все файлы в этой команде имеют *.c
расширение. Простите, что относился к вам как к новичку, но я не могу предположить, что вы что-то знаете, или я рискну дать неправильный ответ. *.c
является каноническим расширением файла для С исходные файлы. Набор инструментов gnu является довольно гибким программным обеспечением, и вы Можно компилировать С код с g++
без ошибок большую часть времени. Но вы не должны, потому что вы получите эту ошибку. Так как ваш исходный файл, mushroom.c
, это С Исходный файл, это будет работать для вас, чтобы просто скомпилировать код как С (в этом случае с gcc
не g++
). Если, однако, вы используете в своей программе такие вещи, как iostream
или же string
или классы или любые другие C ++ код, вы правы, чтобы скомпилировать его как C ++ (условно вы можете изменить расширение на *.cpp
для пояснения, но я не уверен, что GNU toolchain заботится). В этом случае, когда вы хотите включить С код в вашем C ++ программа, обязательно заверните ее в extern "C"{}
, так что компилятор знает соглашения о вызовах и метки С стандарт, который не всегда совпадает с C ++ стандарт. Это означает, что не только звонки С код из C ++ без extern "C"
рискует передать аргументы функциям неверным способом (хороший способ вызвать segfault), но способ, которым переменные и функции переименовываются при компиляции в сборку, различен для двух языков, поэтому вы получаете Undefined Reference
на этапе компоновки, но не на этапе компиляции. В этом случае не только doublefann.c
С исходный файл (который сам по себе прекрасно связывается), но также и библиотека, которая содержит объявление функции GetTickCount()
, В частности, вы ссылаетесь на %SYSTEMROOT%\System32\kernel32.dll
(обычно, но я считаю, что MinGW использует PATH_TO_MinGW\lib\lib32k.a
), который определяет, как программы могут взаимодействовать с операционной системой Windows на уровне машинного кода. __stdcall
Утилита определяется здесь, чтобы называть такие вещи, как GetTickCount()
от ОС, которые являются функциями сборки, в пределах С код. Потому что это в *.dll
, компилятор не может измениться __stdcall
в соответствии с C ++ coventions. Это связано с тем, что «dll
«обозначает»Динамически связанная библиотека«. По сути это означает, что эти файлы уже были скомпилированы в машинный код при установке Windows (или MinGW). Поэтому редактирование бессмысленно, потому что вам понадобятся глубокие рабочие знания кодов операций для каждого когда-либо созданного процессора x86_64. Таким образом звонит в С будет делать все так, чтобы __stdcall
ожидает, но звонит в C ++ требует extern "C"
или он искажает имена объявлений вашей функции и может вызвать ошибки во время выполнения.
FANN написано в С, С= / =C ++, так что не ожидайте C ++ компилятор, чтобы всегда компилировать С код отлично.
Есть два способа решить эту проблему.
Если вы используете 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 */
Не волнуйтесь, они не конфликтуют. Честно говоря, я не уверен, что эти строки предназначены для достижения, но я уверен, что они знают, что они делают.
Если mushroom.c
на самом деле просто чисто С, просто скомпилируйте, используя:
gcc -o shroom.exe mushroom.c -lm -I src\ -I src\ -I src\include\ src\doublefann.c -Wall
и это должно работать. я добавил -Wall
потому что мне нравится, когда я могу сделать свой код абсолютно совершенным, не стесняйтесь оставлять это, он просто печатает все ваши предупреждения.
Других решений пока нет …