简体   繁体   中英

Undefined Symbol When Mixing C and C++ Code

I'm just getting started using nauty, which is written in C. Nauty comes with a program called geng that produces a file of graphs, but it's possible to call it from your own program, and work with the graphs one at a time. A sample C program is provided, and I'm trying to convert it to C++. The comments at the top of the program describe the general approach. I've listed both my program and geng.c, the source code from nauty, in my target.

Here's my code

/* 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;
}

The program geng.c contains the lines:

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

When I try to build the project, it fails with a linker error:

Undefined symbols for architecture x86_64: "_geng_main", referenced from: _main in my_callgeng.o ld: symbol(s) not found for architecture x86_64

I tried compiling from the command line and it works fine.

>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.

So, it looks like an Xcode problem.

In your code (not geng.c), you need to add the extern "C" in front of int GENG_MAIN(int argc, char *argv[]) so that the compiler knows that this function (from geng.c) must use C linkage within your C++ instead of the default C++ linkage for that function (what you get when you don't specify in a file full of C++ code).

Basically, the C++ file uses C++ linkage for functions by default, and the C code uses C linkage for functions, so when you want the C code to be able to call something from the C++ code (your GENG_MAIN) you must specify in the C++ code that that particular function must be compiled with C linkage even though it is internally C++.

This was an Xcode error. I didn't realize that I had to put the compiler flags on each each line under BuildPhases/Compile Sources , so I only had "-DGENG_MAIN=geng_main" for my code, not for geng.c. Therefore the substitution didn't take place when geng.c was compiled, and it must have compiled _main, not _geng_main.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM