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

Undefined Symbol When Mixing C and C++ Code

我刚开始使用 nauty,它是用 C 语言编写的。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

当我尝试构建项目时,它因链接器错误而失败:

Undefined symbols for architecture x86_64: "_geng_main", referenced from: _main in my_callgeng.o ld: symbol(s) not found for architecture 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 问题。

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

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

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