混合C和C ++代码时未定义的符号

时间:2017-04-27 19:51:49

标签: c++ c xcode linker-errors

我刚刚开始使用用C编写的nauty.Nauty带有一个名为geng的程序,可以生成一个图形文件,但是可以从你自己的程序中调用它,一次一个地使用图表。提供了一个示例C程序,我试图将其转换为C ++。该计划顶部的评论描述了一般方法。我已经在我的目标中列出了我的程序和来自nauty的源代码geng.c.

这是我的代码

/* This is a sample of how to call geng as a procedure rather than
 * running it as a separate process.  The basic idea is to construct
 * an argument list for geng's main() function.  At compile time,
 * assign a name to the macros OUTPROC and GENG_MAIN.  A typical
 * Unix-style compilation command would be:
 gcc -o callgeng -O3 -DMAXN=32 -DOUTPROC=myoutproc -DGENG_MAIN=geng_main \
 callgeng.c geng.c nauty.a
 */

extern "C" {
#include "gtools.h"
}

static unsigned long counter;

extern "C" void
OUTPROC(FILE *outfile, graph *g, int n)
{
    /* This will be called for each graph. */

    ++counter;
}


int GENG_MAIN(int geng_argc, char* geng_argv[]);

int
main(int argc, char *argv[])
{
    int geng_argc;
    char *geng_argv[6];

    // Set up geng argument list.  The 0-th argument is the command name.
    // There must be a NULL at the end.  This example is for trees
    // of order 16.

    char argv0[] = "geng";
    char argv1[] = "-q";
    char argv2[] = "-cbf";
    char argv3[] = "16";
    char argv4[] = "15";


    geng_argv[0] = argv0;
    geng_argv[1] = argv1;
    geng_argv[2] = argv2;
    geng_argv[3] = argv3;
    geng_argv[4] = argv4;
    geng_argv[5] = NULL;
    geng_argc = 5;

    counter = 0;
    GENG_MAIN(geng_argc,geng_argv);

    printf("Number of graphs = %lu.\n",counter);

    return 0;
}

程序geng.c包含以下行:

#ifdef GENG_MAIN
int
GENG_MAIN(int argc, char *argv[])
#else
int
main(int argc, char *argv[])
#endif

当我尝试构建项目时,它失败并出现链接器错误:

  

架构x86_64的未定义符号:" _geng_main",引用   从:         _main in my_callgeng.o ld:找不到架构x86_64的符号

我尝试从命令行编译,它运行正常。

>gcc -o callgeng -O3 -DMAXN=32 -DOUTPROC=myoutproc -DGENG_MAIN=geng_main -I/Users/saul/nauty26r7  my_callgeng.cpp ~/nauty26r7/geng.c ~/nauty26r7/nauty.a

>./callgen
Number of graphs = 19320.

所以,它看起来像是一个Xcode问题。

2 个答案:

答案 0 :(得分:0)

在您的代码中(不是geng.c),您需要在前面添加extern“C” INT GENG_MAIN(int argc,char * argv []) 这样编译器就知道这个函数(来自geng.c)必须在C ++中使用C链接而不是该函数的默认C ++链接(当你没有在一个充满C ++代码的文件中指定时你会得到什么)。 / p>

基本上,C ++文件默认使用C ++链接作为函数,C代码使用C链接作为函数,所以当你希望C代码能够从C ++代码(你的GENG_MAIN)中调用某些内容时,你必须指定在C ++代码中,即使它是内部C ++,也必须使用C链接编译该特定函数。

答案 1 :(得分:0)

这是一个Xcode错误。我没有意识到我必须在BuildPhases/Compile Sources下的每一行上放置编译器标志,所以我只有" -DGENG_MAIN = geng_main"对于我的代码,而不是geng.c.因此,在编译geng.c时,替换不会发生,并且必须编译_main,而不是_geng_main。