【问题标题】:How to use a function defined in another file with g++?如何使用g ++在另一个文件中定义的函数?
【发布时间】:2014-08-29 17:05:07
【问题描述】:

这是一个非常基本的问题,我在网上找到了很多概念性的答案,但未能真正发挥作用。

这是我所拥有的:

文件来源.cc

#include <iostream>

int myfunc() {
  return 42;
}

int main() {
  return 0;
}

然后我通过以下方式创建一个目标文件 source.o:

g++ -c source.cc

最后,我使用

ar rvs source.a source.o

获取 source.a 静态库。

现在,麻烦来了。

文件 user.cc 如下所示:

#include <iostream>
#include <source.a>

int main() {
  std::cout << myfunc();
}

我显然想使用库中定义的函数,但是在尝试编译 user.cc 时:

g++ user.cc -o user

我得到的错误是:

user.cc:2:22: fatal error: source.a: No such file or directory
compilation terminated.

【问题讨论】:

  • 尖括号通常不会搜索当前目录,但这不是重点。我非常怀疑您是否要包含 .a 文件。链接到它。
  • 你没有包含一个库,你链接一个库。您还需要函数的声明(通常放在头文件中)。您可能还会看到链接也定义了 main 的库时出现问题。

标签: c++ linker g++


【解决方案1】:

#include 是编译时间,必须是包含例如 this 的 C/C++ 头文件(不是库)

extern int myfunc();

你必须使用链接器来编译它(在命令行上指定所有需要的文件)

【讨论】:

  • 删除extern,这是多余的
  • 但我认为这是一种很好的做法,因为变量需要它。拥有它还不错,您不必考虑在哪里需要它,在哪里不需要。
  • @firda:老实说,用extern 导出全局变量在我看来不是一个很好的做法......如果你真的需要共享某种形式的全局状态,你可能想要导出一些getter/setter 函数。我同意在 C++ 中 extern 导出函数是多余的,应该删除:我不喜欢它,就像我不喜欢 foo(void) 一样,而是更喜欢 C++ 中更简单、更清晰的 foo()
  • 我确实使用foo() 并在旧代码中重写任何foo(void),但不能同意getter,为什么?为什么这是不好的做法?全球shared_mutex呢?这是一个完美的例子,您是否更愿意返回 lock_guardunique_lockshared_lock 之类的少数 getter?
【解决方案2】:

除了其他人已经写过的关于在命令行中正确使用 g++ 的语法之外,您可能需要考虑以下关于您的代码组织的注释。

在您的库代码中,您应该定义main() 函数。 main() 的定义应该是使用您的库的代码的一部分,即您的示例中的文件user.cc

此外,您可能希望向库的客户分发一个头文件,他们可以使用该文件来导入库导出的函数的声明

所以,考虑定义一些像这样的文件:

头文件:

// library.h -- Public header for your library's clients

#pragma once   // or use #ifndef/#define/#endif "header guards"

// Functions exported by your library: 
// their *declarations* go in the library's public header file;
// their *definitions* go in the library's implementation file(s) (.cc, .cpp)
// (exception: inline functions/methods, that are implemented in headers).

int myfunc();

// Add some other exported functions...

// NOTE: "extern" not needed in C++!

实施文件:

// library.cc -- Library implementation code
#include "library.h" // library public header 
#include <...>       // headers required by this implementation code

// *Define* functions exported by the library

int myfunc() {
    return 42;
}

// ...other function implementations...

然后,图书馆的客户端就会这样做:

包含main() 并使用您的库的文件:

// main.cc (or user.cc or whatever you call it)

#include <iostream>   // For std::cout, std::endl
...#include any other required header file...

#include "library.h"  // Your library public header file

int main() {
    // Call library's function
    std::cout << myfunc() << std::endl;
}    

// NOTE: main() is special: "return 0;" can be omitted.

【讨论】:

  • 非常感谢,这让我明白了很多!现在有了头文件source.h和source.cc,我把main.cc编译成了main.o,还需要链接库吗?
  • @mihapriimek:我很高兴它有帮助。顺便说一句:作为一个优秀的 Stackoverflow 公民,您可能希望对所有您认为有帮助的答案进行投票(这个帖子中有几个),并将最佳答案标记为答案。
  • 当然,我只是想通过尝试人们建议的所有不同方法来找出哪一个对我的帮助最大。 (在支持特定答案之前)
  • 能否请教一下在库中包含库头的意义?没有它它也能工作。另外,“”是否也意味着在当前目录中搜索?
  • 可能你的情况很简单,但一般情况下你可以在库头中定义结构和类,并且可以在库实现代码中引用和使用它们,因此需要包含库library.cc 文件中的标头。
【解决方案3】:

不要#include 图书馆档案。它不包含源代码。它包含目标代码。将其放在链接器的命令行中。

使用g++ -c user.cc 编译。 链接g++ -o user user.o source.a

【讨论】:

    【解决方案4】:

    在 C++(和 C99)中,您调用的每个函数都被提前声明。为此,您需要提供函数的“签名”,而无需定义。在你的情况下,这将是声明

    int myfunc();
    

    告诉编译器myfunc 是一个不带参数并返回int 的函数。通常你会在头文件中包含这个函数声明。

    .a 文件是不包含 C 或 C++ 代码的已编译存档,因此将 #include-ing 到 C++ 文件中将不起作用。相反,您需要创建一个 C 或 C++ 标头,并将 .a 存档添加到要链接到最终可执行文件的文件列表中。使用g++,这很容易,你可以说

    g++ user.cc source.a -o executable
    

    例如。

    【讨论】:

      【解决方案5】:

      默认情况下,#include &lt;...&gt; 构造(带尖括号)搜索系统目录以查找指定文件。要搜索其他目录,您可以使用-L 选项,要与您的库链接,您需要在命令行中使用source.a。像这样:

      g++ user.cc -L/path/to/library source.a -o user
      

      【讨论】:

        【解决方案6】:

        添加到讨论中的一些想法 1)您应该创建一个名为 source.h 的头文件,其中包含该行

        int myfunc(); 要么, extern int myfunc();

        2) 在 user.cc 的顶部应该是一行 包括“source.h” 这将告诉编译器该函数已定义

        3) 我认为你应该将 main 函数从 source.cc 中取出,或者至少将其设为静态

        正如其他人指出的那样,您不能包含库文件 (source.a) 您的编译和链接过程应该按原样工作。

        【讨论】:

          【解决方案7】:

          您可以使用#include 来使用headear 文件。如果你想使用库,你必须告诉链接器去哪里寻找库文件。

          查看这些文章了解静态和动态库:

          Static and dynamic libraries

          Using libraries in VS2005

          Using libraries in Code::Blocks

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-04-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-01-15
            相关资源
            最近更新 更多