Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cython compiling error: multiple definition of functions

I create a c file named test.c with two functions defined as follows:

#include<stdio.h>
void hello_1(void){
    printf("hello 1\n");
}
void hello_2(void){
    printf("hello 2\n");
}

After that, I create test.pyx as follows:

import cython
cdef extern void hello_1()

The setup file is as follows:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

setup(cmdclass={'buld_ext':build_ext}, 
      ext_modules=[Extension("test",["test.pyx", "test.c"], 
                   include_dirs=[np.get_include()],
                   extra_compile_args=['-g', '-fopenmp'],
                   extra_link_args=['-g', '-fopenmp', '-pthread'])
    ])

When I run setup file, it always reports hello_1 and hello_2 have multiple definitions. Can anybody tell me the problem?

like image 761
hanqiang Avatar asked Oct 08 '13 23:10

hanqiang


People also ask

What is multiple definition error in C?

What is multiple definition error in C? If you put a definition of a global variable in a header file, then this definition will go to every . c file that includes this header, and you will get multiple definition error because a varible may be declared multiple times but can be defined only once.20-Jul-2013.

What is multiple main error?

Multiple definition of main means you have written main function more than once in your program which is not correct according to C language specifications.


1 Answers

There are a number of things wrong with your files as posted, and I have no idea which one is causing the problem in your real code—especially since the code you showed us doesn't, and can't possibly, generate those errors.

But if I fix all of the obvious problems, everything works. So, let's go through all of them:

Your setup.py is missing the imports at the top, so it's going to fail with a NameError immediately.

Next, there are multiple typos—Extenson for Extension, buld_ext for build_ext, and I think one more that I fixed but don't remember.

I stripped out the numpy and openmp stuff because it's not relevant to your problem, and it was easier to just get it out of the way.

When you fix all of that and actually run the setup, the next problem becomes immediately obvious:

$ python setup.py build_ext -i
running build_ext
cythoning test.pyx to test.c

You're either overwriting your test.c file with the file that gets built from test.pyx, or, if you get lucky, ignoring the generated test.c file and using the existing test.c as if it were the cython-compiled output of test.pyx. Either way, you're compiling the same file twice and trying to link the results together, hence your multiple definitions.

You can either configure Cython to use a non-default name for that file or, more simply, follow the usual naming conventions and don't have a test.pyx that tries to use a test.c in the first place.

So:


ctest.c:

#include <stdio.h>
void hello_1(void){
    printf("hello 1\n");
}
void hello_2(void){
    printf("hello 2\n");
}

test.pyx:

import cython
cdef extern void hello_1()

setup.py:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

setup(cmdclass={'build_ext':build_ext}, 
      ext_modules=[Extension("test",["test.pyx", "ctest.c"], 
                   extra_compile_args=['-g'],
                   extra_link_args=['-g', '-pthread'])
    ])

And running it:

$ python setup.py build_ext -i
running build_ext
cythoning test.pyx to test.c
# ...
clang: warning: argument unused during compilation: '-pthread'
$ python
>>> import test
>>>

Tada.

like image 177
abarnert Avatar answered Sep 28 '22 08:09

abarnert