g++ - 查找合适的Windows库进行链接,以便编译FANN库

g++ - Finding appopriate Windows libraries to link so as to compile FANN library

本文关键字:链接 FANN 编译 查找 g++ Windows      更新时间:2023-10-16

出于各种原因,我一直在尝试自己编译 FANN 库。我在Windows 10上与MinGW合作。为了简单起见,我打算从这样的事情开始:

g++ mushroom.c -o shroom.exe -lm -I src -I srcinclude srcdoublefann.c

(mushroom.c包括<stdio.h>"fann.h"

使用 -I src -I srcinclude srcdoublefann.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);

简而言之,这似乎是链接窗口库的错误,我真的不知道如何继续以找到要链接的相关库。

这是完整的fann.h和完整的doublefann.c

责声明和注释

编辑

:自从昨晚睡觉以来,我改进了我的方法,因此您不必编辑实际的FANN源文件。(作为记录,我原来的方法有效,如果你真的关心,你可以看看编辑历史,看看那是什么(。

首先,对于其他偶然发现这个问题的人,我应该指出,以这种方式使用 FANN 并不是真的必要。该网站提供了cmake文件以及Visual Studio Solutions,两者都可以正常工作。

 

怎么了

回头看这个问题,问题很明显,我讨厌自己在第一个小时之前没有看到它。您会注意到该命令中的所有文件都具有*.c扩展名。请原谅我像对待新手一样对待你,但我不能假设你什么都知道,否则我冒着给出错误答案的风险。 *.cC 源文件的规范文件扩展名。GNU 工具链是一个相当灵活的软件,大多数时候你可以用g++编译 C 代码而不会出错。但你不应该,因为你会收到这个错误。由于您的源文件 mushroom.c 是 C 源文件,因此您只需将代码编译为 C(在本例中为 gcc ,而不是 g++ (。但是,如果你在程序中使用诸如iostreamstring或类或任何其他C++代码之类的东西,那么将其编译为C++是正确的(按照惯例,您会将扩展名更改为*.cpp以进行澄清,但我不确定GNU工具链是否关心(。在这种情况下,每当您想在C++程序中包含 C 代码时,请务必将其包装在 extern "C"{} 中,以便编译器知道调用约定和标签是 C 标准,这并不总是与C++标准相同。这意味着不仅在没有extern "C"的情况下从C++调用 C 代码可能会以错误的方式将参数传递给函数(导致段错误的好方法(,而且当编译为汇编时重命名变量和函数的方式在两种语言之间是不同的,这就是为什么你在链接阶段得到Undefined Reference, 但不是编译阶段。在这种情况下,不仅doublefann.c C 源文件(它本身链接良好(,而且包含 GetTickCount() 函数声明的库也是如此。具体来说,你链接到%SYSTEMROOT%System32kernel32.dll(通常,但我相信MinGW使用PATH_TO_MinGWliblib32k.a(,它定义了程序如何在机器代码级别与Windows操作系统交互。此处定义了 __stdcall 实用程序,用于在 C 代码中调用操作系统中的 GetTickCount() 等内容,这些函数是程序集函数。因为这是在*.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 */

别担心,这些似乎并不冲突。坦率地说,我不确定这些台词的目的是什么,但我相信他们知道他们在做什么。

阿拉伯数字

如果mushroom.c真的只是纯 C,只需使用以下方法编译:

gcc -o shroom.exe mushroom.c -lm -I src -I src -I srcinclude srcdoublefann.c -Wall

这应该有效。我添加了-Wall因为我喜欢能够使我的代码绝对完美,请随意省略它,它只是打印您可能拥有的每个警告。