Reputation: 8423
----------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
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