未定义的引用错误,但库中存在符号

时间:2015-09-03 14:39:24

标签: c gcc linker

我在下面的示例中遇到Task<BStuff>错误。我已经看到很多与此问题相关的问题,但我相信我提供了一个剥离的,可重现的概念性示例,而不是其他问题中的具体问题,

dynlib.h:

public static class Asynchronous
{
    public async static Task DoTheWholeThing(CancellationToken cancellationToken)
    {
        var getAStuffTask  = new Func<Task<AStuff>>(
                async () =>
                    {
                        using (var a = new A())
                        {
                            return await a.GetStuffAsync(cancellationToken);
                        }
                    })();

        var getBStuffTask  = new Func<Task<BStuff>>(
                async () =>
                    {
                        using (var b = new B())
                        {
                            return await b.GetStuffAsync(cancellationToken);
                        }
                    })();

        var combination = CombineStuff(
            await getAStuffTask,
            await getBStuffTask);
    }

    private Combination CombineStuff(AStuff aStuff, BStuff bStuff)
    {
        //// Magic Here
    }
}

dynlib.c:

undefined reference

myapp.c:

void printMe_dyn();

构建步骤:

#include <stdio.h>
#include "dynlib.h"

void printMe_dyn() {
  printf("I am execuded from a dynamic lib");
}

错误:

#include <stdio.h>
#include "dynlib.h"

int main() 
{
    printMe_dyn();
    return 0;
}

证明该符号在库中:

gcc -Wall -fpic -c dynlib.c
gcc -shared -o libdynlib.so dynlib.o
gcc -Wall -L. -ldynlib myapp.c -o myapp
  1. 我是否使用正确的编译器标志来构建动态 图书馆?
  2. 我所提供的证据真的是一个明确的证明吗?
  3. 可以采取哪些其他方法来诊断问题?

3 个答案:

答案 0 :(得分:2)

库的出现顺序重要

引用online gcc manual

  

在您编写此选项的命令中,它会有所不同;链接器按照指定的顺序搜索和处理库和目标文件。因此,foo.o -lz bar.o在文件z之后但foo.o之前搜索库bar.o。如果bar.o引用z中的函数,则可能无法加载这些函数。

您应该将编译语句更改为

gcc -o myapp -Wall -L. myapp.c -ldynlib 

告诉gcc搜索myapp.c中存在的(已编译)dynlib中使用的符号

答案 1 :(得分:1)

链接器命令行中库的顺序很重要。修正:

gcc -o myapp -Wall -L. myapp.c -ldynlib 

答案 2 :(得分:0)

仅作为附加通知。当库由gcc构建并链接到c ++项目时,可能会获得相同的行为。如下所示:

gcc -Wall -fpic -c dynlib.c
gcc -shared -o libdynlib.so dynlib.o
g++ -o myapp -Wall -L. myapp.cpp -ldynlib

在这种情况下,原因是g ++使用了名称修饰。要关闭它,必须在C库中用extern "C"包装C函数原型。例如如下:

dynlib.h:

#ifdef __cplusplus
extern "C"{
#endif
void printMe_dyn();
#ifdef __cplusplus
}
#endif