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 потому что мне нравится, когда я могу сделать свой код абсолютно совершенным, не стесняйтесь оставлять это, он просто печатает все ваши предупреждения.

Другие вопросы по тегам