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.