2

I'm trying to learn Cython and have managed to compile .pyx with the function definition straight in the file.

My next step is trying to compile .pyx linking external C functions. The compilation succeeds but when I'm trying to import the module in a Python script the function is not found.

In file "Cython-C.pyx":

cdef extern from "svar.h":
    unsigned long long int svar()

In file "setup.py":

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
ext_modules = [Extension(name="Nej", sources=["Cython-C.pyx"])]
setup(
      name = 'blublu',
      cmdclass = {'build_ext': build_ext},
      ext_modules = ext_modules
)

I've tried different sources based on answers around the net such as: sources=["Cython-C.pyx"])], sources=["svar.h","Cython-C.pyx"])], sources=["svar.c","Cython-C.pyx"])] etc..

In file "svar.c":

#include "svar.h"

unsigned long long int svar(){
unsigned long long int i;
unsigned long long int c;
for(i=0; i<100000000; ++i)
{
    c=i/(i+1);
}
return c;
}

In file "svar.h":

unsigned long long int svar();

I compile it on windows using:

python setup.py build_ext --inplace

In file "CWrapperTest.py":

import Nej

print(Nej.svar())

Results in "AttributeError: module 'Nej' has no attribute 'svar'"

And Nej does indeed not contain "svar":

dir(Nej)
Out[2]: 
['__builtins__',
 '__doc__',
 '__file__',
 '__loader__',
 '__name__',
 '__package__',
 '__spec__',
 '__test__']

My goal is just trying to get the absolute most basic thing working for learning purposes. I don't think the documentation is clear enough on this issue.

Stephane Rolland
  • 38,876
  • 35
  • 121
  • 169
CupinaCoffee
  • 457
  • 4
  • 14
  • @ead - I'm being unhelpful here (sorry). I'd confirmed your [duplicate suggestion](https://stackoverflow.com/questions/30228821/importing-cython-function-attributeerror-module-object-has-no-attribute-fun) but on a closer look this is about `cdef extern` while your suggestion was about `cdef`. I think that's sufficiently different that it isn't _really_ a duplicate so I undid it (but unfortunately it has the overall effect of removing your vote on it). – DavidW Jul 19 '20 at 20:43

1 Answers1

3

External C functions are only exported as far as Cython - they aren't directly callable from Python. You need to create a Cython wrapper function:

cdef extern from "svar.h":
    unsigned long long int svar()
def svar_py():
    return svar()

You'll be able to call svar_py from Python.

(To my slight surprise this doesn't seem very well documented and perhaps should be).


The correct line in the setup.py file will be

sources=["svar.c","Cython-C.pyx"])]
DavidW
  • 29,336
  • 6
  • 55
  • 86