1

我已经使用开源库(“快速人工神经网络”)工作了一段时间。我在我的静态库中使用它的源代码。然而,当我编译它时,我收到数百个链接器警告,这可能是由于库在其他 *.c 文件中包含它的 *.c 文件(因为我只包括一些我需要的头文件而我没有触及lib本身的代码)。

我的问题:图书馆的开发人员是否有充分的理由使用这种强烈反对的方法?(或者至少我一生都被告知这很糟糕,根据我自己的经验,我认为这很糟糕)。或者它只是糟糕的设计,这种方法没有任何收获?

我知道这个相关的问题,但它没有回答我的问题。我正在寻找可能证明这一点的理由。

一个额外的问题:有没有办法在不过多接触库代码的情况下解决这个问题?我有很多自己的工作,不想创造更多;)

4

6 回答 6

3

据我所知(grep '#include .*\.c'),他们只在 doublefann.c、fixedfann.c 和 floatfann.c 中这样做,并且每次都包含原因:

/* Easy way to allow for build of multiple binaries */

这种将预处理器用于简单复制粘贴的确切用途确实是包含实现 (*.c) 文件的唯一有效用途,而且相对较少。(如果您出于其他原因想要包含一些代码,只需给它一个不同的名称,例如 *.h 或 *.inc。)另一种方法是在给编译器的宏中指定配置(例如 -DFANN_DOUBLE、-DFANN_FIXED 或-DFANN_FLOAT),但他们没有使用这种方法。(每种方法都有缺点,所以我并不是说它们一定是错误的,我必须深入研究该项目才能确定这一点。)

他们提供了 makefile 和 MSVS 项目,这些项目不应doublefann.o(来自 doublefann.c)与 fann.o(来自 fann.c)或 fixedfann.o(来自 fixedfann.c)等链接,并且它们的文件是搞砸了或类似的事情出错了。

您是否尝试从头开始创建项目(或使用现有项目)并将所有文件添加到其中?如果你这样做了,发生的事情是每个实现文件都被独立编译,并且生成的目标文件包含冲突的定义。这是处理实现文件的标准方式,许多工具都采用这种方式。唯一可能的解决方案是修复项目设置以不将它们链接在一起。(好吧,你也可以彻底改变他们的来源,但这并不是真正的解决方案。)

当你这样做的时候,如果你继续不使用他们的项目设置,你可能会跳过编译 fann.c 等。人。并且可能只是从项目中删除它们就足够了——那么它们就不会被编译和链接。您需要准确地选择一个double-/fixed-/floatfann 来使用,否则您将得到相同的链接错误。(我没有看过他们的说明,但看​​到这个摘要在那里更深入地解释了一点,我不会感到惊讶。)

于 2010-07-12T09:23:42.087 回答
2

包含 C/C++ 代码会导致所有代码集中在一个翻译单元中。使用一个好的编译器,这可以带来巨大的速度提升(因为可以内联内容并优化函数调用)。

但是,如果要像这样包含实际代码,则它static的大部分声明中都应该包含它,否则它将导致您看到的警告。

于 2010-07-12T09:05:36.720 回答
0

我现在正在家里这样做,因为我是 Linux 上 C++ 的相对新手,并且不想陷入链接器的困难中。但我不建议将它用于正常工作。

(我也曾经不得不将 header.dat 包含到 C++ 程序中,因为 Rational Rose 不允许标头成为已发布软件的一部分,并且我们需要运行系统上的特定源文件(出于神秘原因)。)

于 2010-07-12T09:25:35.697 回答
0

如果您曾经在该 .c 文件中声明单个全局变量或函数,则不能将其包含在两个都编译为相同二进制文件的位置,否则两个定义将发生冲突。如果它被包含在一个地方,它也不能被单独编译,同时仍被链接到与其用户相同的二进制文件中。

如果文件只包含在一个地方,为什么不把它变成一个离散的编译单元(并通过extern声明使用它的全局变量)?为什么要费心把它包括在内?

如果你的 C 文件没有声明全局变量或函数,它们是头文件,应该这样命名。

因此,通过详尽的搜索,我可以说,唯一可能想要包含 C 文件的情况是,相同的 C 代码用于构建多个不同的二进制文件。即使在那里,你也在增加编译时间而没有真正的收获。

这是假设应该内联的函数被标记inline并且你有一个体面的编译器和链接器。

我不知道解决此问题的快速方法。

于 2010-07-12T09:05:21.760 回答
0

我不知道那个库,但正如你所描述的那样,这要么是不好的做法,要么是你对如何使用它的理解不够好。

想要被其他人包含的 AC 项目应始终为其他人提供结构良好的 .h 文件,然后为链接提供编译的库。如果它想在头文件中包含函数定义,它应该将它们标记为static(老式)或inline(可能从 C99 开始)。

于 2010-07-12T09:09:20.107 回答
0

我没有查看代码,但是包含的 .c 或 .cpp 文件可能实际上包含在标头中工作的代码。例如,模板或内联函数。如果是这种情况,那么警告将是虚假的。

于 2010-07-12T09:09:31.430 回答