3

I am learning how to use Cython to compile efficiently a Python code and make it quicker.

Here is what I've done so far:

  1. I created a Python file called math_code_python.py and put 4 simple functions in it.
  2. I saved that file as math_code_cython.pyx.
  3. I created a setup file called setup.py.
  4. I typed python C:\Users\loic\Documents\math_code\setup.py build_ext --inplace in my Command Prompt.
  5. I got a compiled file called math_code_cython.cp36-win_amd64.pyd that I renamed math_code_pyd.pyd.
  6. Finally, I created a Python file called test_math_code.pyd with only import math_code_pyd in it. When I executed this file I got that message:

    ImportError: dynamic module does not define module export function
    

I did some research and thanks to those posts I understood that I had to provide an init function:

My question is : how do I do that ? Do I have to put a function at the end of math_code_python.py like what follows ?

def __init__(self):
    # something ?

My version of Python:

Python 3.6.1 |Anaconda 4.4.0 (64-bit)| (default, May 11 2017, 13:25:24) [MSC v.1900 64 bit (AMD64)]

math_code_python.py

def fact(n):
    if n==0 or n==1:
        return 1
    else:
        return n*fact(n-1)

def fibo(n):
    if n==0 or n==1:
        return 1
    else:
        return fibo(n-1)+fibo(n-2)

def dicho(f, a, b, eps):
    assert f(a)*f(b) < 0
    while b-a > eps:
        M = (a+b)/2.
        if f(a) * f(M) > 0:
            a = M
        else:
            b = M
    return M

def newton(f, fp, x0, eps):
    u = x0
    v = u - f(u)/fp(u)
    while abs(v-u) > eps:
        u = v
        v = u - f(u)/fp(u)
    return v

setup.py

try:
    from setuptools import setup
except ImportError:
    from distutils.core import setup

from Cython.Distutils import build_ext
from Cython.Build import cythonize

import numpy as np

setup(name = "maido",
      include_dirs = [np.get_include()],
      cmdclass = {'build_ext': build_ext},
      ext_modules = cythonize(r"C:\Users\loic\Documents\math_code\math_code_cython.pyx"),
      )
Loïc Poncin
  • 511
  • 1
  • 11
  • 30

1 Answers1

2

Your mistake is renaming the pyd file. When you call import math_code_pyd it specifically looks for initmath_code_pyd (Python2) or PyInit_math_code_pyd (Python3).

When you compile it with Cython it generates a function matched to the .pyx filename (i.e. initmath_code_cython or PyInit_math_code_cython). Hence it doesn't find the function it expects to. You don't have to provide this function yourself - Cython generates it.

Simply name your .pyx file what you want your module to be called and don't rename the .pyd file. (In principle you could remove the .cp36-win_amd64 but it is useful and there for a reason).

DavidW
  • 29,336
  • 6
  • 55
  • 86