Yuxiang Wang
Yuxiang Wang

Reputation: 8423

How should I use the `round() ` function in Cython?

----------Update-------------------------

Found some light here.

The downside to this is that the official 64-bit Python build does not ship with libmsvcr90.a, which we need to link with the correct C runtime DLL.

-----------Original post-------------------

My Python version:

Python 3.3.5, with MSC v.1600 64 bit in Windows. Windows SDK v7.1 was installed and used. I have been working with Cython for a week and it seems that it runs other code just fine.

In this link, it said round() is one of the built in functions. However, when I call it in my cython code and use cython my_code.pyx -a to check, the function was pure yellow which means the python method was used.

Then I did some googling, and used:

from libc.math cimport round

but it said "unresolved external symbol" during compilation.

What should I do?

Here is the code:

from libc.math cimport round

cdef float a = 1.5
cdef float b

b = round(a)
print(b)

And it said: fatal error LNK1120: 1 unresolved externals error

My setup.py:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
import numpy as np

extensions = [
    Extension('test', ['test.pyx'], include_dirs = [np.get_include()]),
    ]

setup(
    ext_modules = cythonize(extensions)
    )

I know np.get_include() is really not necessary in this case, but I just added them because I use numpy too often and it wouldn't hurt too much for this case anyway.

My command to compile it:

python setup.py build_ext --inplace

And the result (I actually used setup1.py on my machine):

X:\WorkFolder\DataAnalysis\lw9pg\mol>python setup1.py build_ext --inplace running build_ext
building 'test' extension
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\Bin\amd64\cl.exe /c /nologo /Ox /MD /W3 /GS- /DNDEBUG -IX:\WinPython3\python-3.3.5.amd64\include -IX:\WinPython3\python-3.3.5.amd64\include /Tctest.c /Fobuild\temp.win-amd64-3.3\Release\test.obj
test.c
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\Bin\amd64\link.exe /DLL /nologo /INCREMENTAL:NO /LIBPATH:X:\WinPython3\python-3.3.5.amd64\libs LIBPATH:X:\WinPython3\python-3.3.5.amd64\PCbuild\amd64 /EXPORT:PyInit_test build\temp.win -amd64-3.3\Release\test.obj /OUT:X:\WorkFolder\DataAnalysis\lw9pg\mol\test.pyd /IMPLIB:build\temp.win-amd64-3.3\Release\
test.lib /MANIFESTFILE:build\temp.win-amd64-3.3\Release\test.pyd.manifest
test.obj : warning LNK4197: export 'PyInit_test' specified multiple times; using first specification
Creating library build\temp.win-amd64-3.3\Release\test.lib and object build\temp.win-amd64-3.3\Release\test.exp
test.obj : error LNK2019: unresolved external symbol round referenced in function __pyx_pf_4test_rounding
X:\WorkFolder\DataAnalysis\lw9pg\mol\test.pyd : fatal error LNK1120: 1 unresolved externals
error: command '"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\Bin\amd64\link.exe"' failed with exit status 112
0

Upvotes: 4

Views: 3457

Answers (1)

Padraic Cunningham
Padraic Cunningham

Reputation: 180401

If you want to test simple cython code, the easiest way is using pyximport:

To run yours, assuming the file your code is in is called tester.pyx:

In the same directory, put this at the top of a python file and just run the file, you will see your print b will output 2.0.

import pyximport
pyximport.install()

To compile and run a cython function, I use the following setup.py script:

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

ext= Extension("tester", sources=["tester.pyx"])
setup(ext_modules=[ext],cmdclass={'build_ext': build_ext})

Run it on your .pyx file with the following command, the --inplace compiles it into the same dir :

python setup.py build_ext --inplace --compiler=mingw32 # --compiler=mingw32 only needed on windows

You will have a (tester.pyd) (tester.so on mac and linux) file where you can import your functions from as if they were coming from a python module.

This is a simple function that rounds a number:

from libc.math cimport round

def rounding(float n):
    return round(n)

I compile it or use pyxinstall importing it and running it like:

In [29]: from tester1 import *

In [30]: rounding(12.3453455)
Out[30]: 12.0

Using pyximport:

In [21]: import pyximport

In [22]: pyximport.install()
Out[22]: (None, None)
         from tester import *
In [23]: rounding(10.23232)
Out[23]: 10.0

I created a pure python rounding method to compare:

def py_rounding(n):
    return round(n)

import timeit
if __name__=='__main__':
    print timeit.timeit('py_rounding(10.23232)','from cyt import py_rounding')
    print timeit.timeit('rounding(10.23232)','from tester import rounding')
    0.183354854584
    0.037761926651

The cython code is considerably faster.

These are very basic examples, you can find much better uses for cython here including using the %load_ext cythonmagic using ipython

Upvotes: 3

Related Questions