We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Get native with Cython

00:00

Formal Metadata

Title
Get native with Cython
Title of Series
Part Number
89
Number of Parts
173
Author
License
CC Attribution - NonCommercial - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Identifiers
Publisher
Release Date
Language
Production PlaceBilbao, Euskadi, Spain

Content Metadata

Subject Area
Genre
Abstract
Stefan Behnel - Get native with Cython [Cython] is not only an excellent and widely used tool to speed up computational Python code, it's also a very comfortable way to talk to native code and libraries. The Cython compiler translates Python code to C or C++ code, and supports static type annotations to allow direct use of C/C++ data types and functions. The tight integration of all three languages makes it possible to freely mix Python features like generators and comprehensions with C/C++ features like native data types, pointer arithmetic or manually tuned memory management in the same code. This talk by a core developer introduces the Cython compiler by interactive code examples and presents recent enhancements in the language that continue to make Cython the best choice for the development of fast and portable Python extensions.
Keywords
51
68
Thumbnail
39:40
108
Thumbnail
29:48
Mobile appReading (process)Software developerSocial softwareData miningÄhnlichkeitssucheService (economics)WordSoftware developerCartesian coordinate systemSemiconductor memoryInformation technology consultingPay televisionCentralizer and normalizerOpen sourceProjective planePresentation of a groupBitNumberWebsiteWave packetMoment (mathematics)Web pageReading (process)E-bookSinc functionLecture/ConferenceComputer animation
Social softwareData miningÄhnlichkeitssucheMachine codeMathematical optimizationFluid staticsModul <Datentyp>Integral elementCompilerProgramming languageSimilarity (geometry)E-bookPay televisionService (economics)Open sourceLattice (order)Library catalogScaling (geometry)Source codeData miningCellular automatonLevel (video gaming)Hydraulic jumpComputer animation
Machine codeFluid staticsMathematical optimizationModul <Datentyp>Integral elementOpen sourceCompilerProgramming languageHand fanModule (mathematics)Library (computing)Interior (topology)Task (computing)Computer fileSocial classCompilerRevision controlDifferent (Kate Ryan album)Source codeLine (geometry)Scripting languageBuildingConfiguration spaceExt functorPortable communications deviceMachine codeComputing platformData conversionActive contour modelRoutingRevision controlState of matterComputing platformCopyright infringementCASE <Informatik>Inheritance (object-oriented programming)CompilerAuthorizationSource codeDifferent (Kate Ryan album)Pattern languageMultiplication signMathematical optimizationEndliche ModelltheoriePower (physics)Line (geometry)Sign (mathematics)Cellular automatonOnline helpGroup actionIntegral elementAuthenticationRoboticsSocial classHuman migrationBuildingLibrary (computing)MetadataConnectivity (graph theory)Inequality (mathematics)WordSoftware maintenanceFunctional programmingOffice suiteMachine codeComputer fileParticle systemPersonal digital assistantCompilerSheaf (mathematics)Programming languageScripting languageSurfaceConfiguration spaceMemory managementCycle (graph theory)Right angleProjective planeComputer programmingPhysical systemImplementationQuicksortMappingModule (mathematics)ArmNumberEntire functionProcess (computing)Logical constantSlide rulePresentation of a groupLogistic distributionHeegaard splittingWritingLinker (computing)BitStandard deviationFluid staticsOrder (biology)Portable communications deviceComputer animation
Portable communications deviceMachine codeCompilerComputing platformCompilerMachine codeProgramming languageSuite (music)Social classMeta elementElectric generatorFunction (mathematics)Algebraic closureData structureProgrammschleifeControl flowObject-oriented programmingOperations researchMathematical analysisFrame problemSoftware bugLinear regressionSoftware testingComplete metric spaceStandard deviationData typeTypinferenzFluid staticsBeta functionBenchmarkInterior (topology)CuboidNatural numberArray data structurePointer (computer programming)Template (C++)Operator (mathematics)Programming languageMachine codeSoftware bugData typeTypinferenzLaptopSuite (music)Multiplication signCompilerRevision controlSoftware testingException handlingMachine codeFluid staticsFunctional programmingBitCartesian coordinate systemAbsolute valueBeta functionMathematical optimizationStandard deviationDirection (geometry)BenchmarkVariable (mathematics)Game controllerComputer configurationAdditionLetterpress printingFrame problemLevel (video gaming)Declarative programmingComputer fileObject-oriented programmingSemantics (computer science)Sinc functionNormal (geometry)Source codeInterpreter (computing)Different (Kate Ryan album)Demo (music)IntegerComputer programmingLinear regressionModulare ProgrammierungOperator (mathematics)Continuous integrationExtension (kinesiology)WeightEqualiser (mathematics)Sampling (statistics)ReliefPattern languageSeries (mathematics)Graph coloringProcedural programmingMereologyIntegral elementTouch typingContext awarenessArmData structureBuildingCASE <Informatik>AreaGroup actionUniverse (mathematics)Student's t-testForm (programming)ConcentricSoftwareSpeech synthesisCompilerSocial classWebsiteProgrammschleifeSymbol tablePresentation of a groupNeuroinformatikMatrix (mathematics)Operator overloadingTemplate (C++)Network topologyPopulation densityPoint (geometry)CuboidDependent and independent variablesMathematicsComputer animation
Normed vector spaceFunction (mathematics)WeightView (database)Beta functionJust-in-Time-CompilerInterior (topology)Kernel (computing)Cellular automatonComputer fileMachine codeIntegerCache (computing)Machine codeError messageMemory managementRead-only memoryAerodynamicsLibrary (computing)MathematicsSineLetterpress printingFreewarePrinciple of maximum entropyCASE <Informatik>Cone penetration testPersonal area networkMetropolitan area networkRaw image formatHash functionHand fanMenu (computing)StrutOvalLine (geometry)State diagramWrapper (data mining)Standard deviationLetterpress printingDeclarative programmingFunctional programmingMultiplication signSet (mathematics)ResultantError messageCombinational logicOntologyEndliche ModelltheorieWordIntegral elementOcean currentForestFunction (mathematics)Semiconductor memoryGame controllerRepresentation (politics)Object-oriented programmingLibrary (computing)Different (Kate Ryan album)Run time (program lifecycle phase)Pattern languagePRINCE2System callInstance (computer science)Content (media)Source codeData typeArmParameter (computer programming)Arithmetic meanSoftware crackingRevision controlPlanningWeb 2.0Social classWebsiteProbability density functionCycle (graph theory)Operator (mathematics)NeuroinformatikData conversionTerm (mathematics)Line (geometry)Memory managementOnline helpIncidence algebraMassFigurate numberDemosceneOperating systemVariable (mathematics)MathematicsState of matterCompilerData bufferConnectivity (graph theory)BitInteractive televisionModule (mathematics)CASE <Informatik>Machine codeDoubling the cubeJust-in-Time-CompilerCompilerCellular automatonLaptopSineEmailDampingAreaStructural loadFreewareComputer animation
Metropolitan area networkMathematicsSineLine (geometry)Machine codeInterior (topology)OvalStrutKernel (computing)Computer fileCellular automatonView (database)Machine codeGlass floatChi-squared distributionString (computer science)Run time (program lifecycle phase)Function (mathematics)NumberData conversionFloating pointFibonacci numberArray data structureUnicodeState of matterLibrary (computing)ProgrammschleifeLoop (music)TupleQuantum stateLetterpress printingSystem callOnline helpSocial classIntegerVector spacePattern languageFunctional programmingSeries (mathematics)Online helpMetric systemCASE <Informatik>Direction (geometry)Category of beingEmailResultantSymbol tableProgram slicingComputer virusRun time (program lifecycle phase)Machine codeMultiplication signLibrary (computing)Rule of inferenceComputer fileSpring (hydrology)String (computer science)Element (mathematics)System callState of matterBenchmarkNumberTexture mappingIterationBitSinc functionBit rateArmSemiconductor memoryIntegerPoint (geometry)Function (mathematics)Error messageLengthRevision controlRow (database)Declarative programmingPresentation of a groupService (economics)Right angleSign (mathematics)Source codeNatural numberRadiusMedical imagingOrder (biology)Object-oriented programmingDirectory serviceException handlingInferenceWave packetEndliche ModelltheorieParticle systemLoginVariable (mathematics)Chemical equationComputer programmingIntegrated development environmentMappingVirtual machineWorkloadQuicksortVarianceAsynchronous Transfer ModeWrapper (data mining)Physical systemConsistencyWordData conversionPartial derivativeLine (geometry)RecursionLeakCompiler10 (number)Letterpress printingArray data structureHeegaard splittingLoop (music)Module (mathematics)Principle of maximum entropySineMessage passingStructural loadComputer animation
Exponential functionVector spaceSocial classIntegerNormed vector spaceBeta functionInversion (music)View (database)Coma BerenicesStructural loadNumberRevision controlIntegrated development environmentCycle (graph theory)Operator (mathematics)Arithmetic meanQuicksortDeclarative programmingSocial classComputer animationLecture/Conference
Computer fileView (database)Cellular automatonKernel (computing)Beta functionVector spaceSocial classIntegerMetropolitan area networkCausalityLevel (video gaming)LaptopMachine codeSystem callMachine codeInterior (topology)MereologyRepetitionInfinityClefMUDMagneto-optical driveLine (geometry)CASE <Informatik>Modul <Datentyp>Extension (kinesiology)WritingSocial classVector spaceoutputIterationPattern languageWebsiteObject-oriented programmingIntegral elementRepresentation (politics)Electronic mailing listWritingWrapper (data mining)Machine codeData typeAttribute grammarMemory managementMappingEndliche ModelltheorieInferenceProgramming languageMathematical optimizationSpeicherbereinigungLevel (video gaming)Extension (kinesiology)Module (mathematics)Library (computing)Semantics (computer science)Field (computer science)CASE <Informatik>Sound effectMultiplication signConcentricMachine codeForceRow (database)Term (mathematics)Logische ProgrammierspracheInstance (computer science)Video gameNatural numberChi-squared distributionComputer programmingSummierbarkeitWordPresentation of a groupWeb pageFunctional programmingData structureLecture/ConferenceComputer animation
DistanceLogic synthesisDependent and independent variablesOperator (mathematics)Group actionSource codeObject-oriented programmingEndliche ModelltheorieWebsiteMachine codeCASE <Informatik>QuicksortDifferent (Kate Ryan album)Standard deviationElectric generatorMultiplication signLevel (video gaming)CompilerLecture/Conference
Transcript: English(auto-generated)
I'm actually happy to have so many people here, so thanks for coming. So a couple of words about myself, I've been a Python developer and an awesome advocate
since the early 2000s, currently working for Scooby, which is an e-book subscription service, so pay a fixed price per month and you get unlimited reading as much as you like. And besides that, I'm a consultant and trainer, so I give Cython trainings, also in-house,
and I'm working on a couple of open source projects from which you may know me, the most well-known two are maybe Alex and Mel and Cython, Looper and a couple of others, so you find them on the page. Okay, since Cython is used a lot in big data applications, so I would like to give you
a bit of background about what we're doing at Scooby. So as I said, it's an e-book subscription service and we actually have a very large catalog, so there's more than 130,000 publisher titles and actual publisher titles, not like
self-publishing something, and that's all books that are available to everyone, every subscriber, anywhere, anytime, you can just click on a book and read it. And once you have a catalog of that size, it becomes kind of tricky to keep it navigable,
okay, so it becomes difficult for people to find their books, find the books they want to read, and so that's the problem we're faced with, and the question is how do I find my next book, right? So there's a lot of stuff you can do, you can have recommendations, editorial recommendations, but they don't really scale to large user bases, personal recommendations, you
can crowd source that, and certainly you're trying to automate a lot of stuff, so you can do a similarity search between users between books, data mining, and so that's a major thing that we're currently working on, and so you come into play, you can actually
help us make our book lovers happy, because we're hiring, okay, so go to that page, find a job, and come and join us, and talk to me in the recruiting session, for example. So for the actual topic of the talk, the topic is Cython, which is, well, what is
Cython? It's a couple of things, first of all it's an open source project, you can find it on Cython.org, it's Python compiler, it's almost a Python compiler, so it translates Python to C plus C API calls, and it features static code optimization for you, it's actually
more than that, in that it's an extended Python language, which allows you to write fast extension modules for C Python, without resorting down to C and writing C API calls itself, and it's a very nice way for interfacing Python with C and C++ libraries.
And over the years, so Cython's actually a relatively old project, it was originally ford from Pyrex, who of you knows Pyrex? Yeah, a couple of people, okay, so Pyrex was a project that was begun by Greg Ewing,
somewhere around the 2000s, and in 2007, Rod Batchell and I ford Pyrex, which had kind of come to a certain stall at the time, and founded the Cython project, and since
then we had a humongous success and a huge rise in our user base, and over the time it's really become a major pillar of the Python ecosystem, especially the scientific Python ecosystem, but it's more general than that.
So by now there are like tons of Cython code out there, and it's certainly, it's kind of a technology endeavor, so as a programming language, it really helps people to get their job done. So how do you use Cython? This talk is kind of split into two parts, okay, so one is a general introduction, I'm
going to tell you a bit about the surroundings and stuff, and how it works in the surface, and then I'll show you a couple of examples afterwards. So in order to use Cython, what you do is you write Python code, or Cython code, as I'll explain later, Cython then translates this into C code, so you need a C compiler
to build a shared library for C Python, and then you can just import it and work with it there. So as you can see, there's an additional hurdle compared to writing Python code and importing it done, right, so you need a compile and build step in between.
So let's compile some Python code, and it's just a stupid little example, so we have a class here, an init method, some method that, you know, gets a, so basically the idea is to put a, it has a function in, and then you call it from this method here, and that's what we do down here, we instantiate the class and then we call
this method, make the function be called a couple of times, and that's it, so really stupid code, just a couple of lines of Python code, and when you run it through Cython, it'll spit out a file, a C file of about 3,300 lines of code, okay?
That sounds huge in comparison, and so in order to get there, it's actually quite simple, we have a script, Cythonize, so you can just say Cythonize minus i built in place, in place, i, Cythonize minus i and you work a file, Python scripts, and
then it's just gonna translate it, it's gonna translate it to C, and then it'll build your extension for you, and then you can, as I said, import it and work with it. So why is that so large? In these 3,000 lines of code, there are, well, there are lots of portability signs, so lots of stuff that says if the C Python version you're compiling against is this,
then optimize something in a different way than for different C Python versions. Very often that's the case for Python 3 and Python 2 differences, but also for new features that came in in your C Python versions, so your code will actually adapt to the C
Python version you're currently building it against, and if it's a newer C Python version, whichever has a certain feature, it's gonna use that, otherwise it'll just fall back to some fallback implementation, and it might be slower, but it's still gonna work. The next thing we do is we copy all the original source code into SQL comments, so
you can actually, when you read the C file, you can actually find your entire source code in there, which makes it easier to figure out what's happening when, and which source code line contributed to what, you know, huge amount of C code, and in any case,
it's definitely, it's definitely a lot of code that you really don't want to write yourself, and for which you want to use a code generator, so rewrite C so you don't have to, okay?
Building the whole thing, I already showed this Cythonized script, which is really nice, but it's kind of the thing you would use for local development, and when you want to distribute your code, you'd use distutils, and you'd let distutils build the extension
module for you, so that users who want to install your package have no problems in building it locally and, you know, getting it all set up. We also have a helper for that, so basically what you do is you would import the Cythonized function, after which the Cythonized script's modeled, and then you would just say, Cythonize
some source files, and it'll build the extension, so the metadata, the extension metadata for you, and it'll compile that for you, okay? For the more involved cases, where you want to build against external libraries, for example, so you have, you know, linker set up and maybe include path and stuff like that,
you can also use this standard distutils way of setting up the build metadata through the extension class. You can configure it, just look it up in the distutils config,
configure it yourself, and then pass that into Cythonize, okay, and then it's just going to do the right thing for you. Okay, so I already mentioned that the code Cython generates is very portable, actually, so it generates SQL that compiles with all major C and C++ compilers, on all major platforms, so Linux, Mac, Windows, and some
others are, well, less often tested, but generally work. And in all C Python versions, from 2.6 through 3.5, which is currently not released, but, you know, it's on the way. Partly also in PyPy, so PyPy is support
for the C API, and we have a lot of special cases in the Cypham generated C code, which say, if compiling for PyPy, then there's otherwise to something else, which help in, A, making it work at all in PyPy, and sometimes making it less inefficient.
So the language syntax of Cython itself follows Python 2.7, with lots of feature back ports, whatever comes in from Python 3, we just adopt it, as long as it doesn't conflict
with any Python 2 features, and if you want to have actual Python 3 syntax, you can use the usual future imports, from future import, absolute import, print function, this kind of stuff, or you can just say, leave a compiler directive at the top of your source
file, which says, language level 3, and then you get Python 3 semantics for your file. For language features, Python language features, one of the tests we run in our continuous integration test is the C Python regression test suite of Python 2.7 and 3.5, and we
are at about 98% success, so it's pretty close to full Python language coverage. What's definitely in there is everything you would normally know, like classes, control structures, loops, try finally, so exception handling, comprehensions, we have support
for async and await, which will be new in Python 3.5, star unpacking, same thing, so this extended star unpacking, which is new in Python 3.5, so that will all be in the
next Python release, which is currently in beta, so we have published a beta release yesterday, so the first beta is out for version 23 of Python, and we have support for profiling, tracing, coverage analysis, like lots of tools that help you understand,
analyze your code, and make it better. Okay, a couple of deviations, we don't have frames inside of functions, who here knows what frames are? Okay, that's definitely a clear minority, so if you never came in touch with frames, then this one usually hurt you.
You'll notice frames in a couple of places, and that's tracebacks, because tracebacks are actually built on frames, but we support those, okay, so you'll get a nice traceback from your Cython code if there's an exception being raised, that's all supported. And
then obviously, yeah, there are bugs in every piece of software, and you can find them in bug tracker. As for speed, so Cython generates actually very efficiency code, and there are many static and optimistic optimizations that it applies to your code. It generates
optimized code for standard types, and for many built-ins that you would use, and has static type inference within functions. Okay, so it kind of can decide what you do and when, and it understands your code in a way that's, so it has better static
knowledge about your code than the normal C Python interpreter would. One way we measure speed is with the Python benchmark series. There's a bunch of software packages that were assembled to measure speed of the performance of Python programs.
It's actually real-world code, including stuff like Django, some template engines, what else is in there, some, yeah, some kind of computational little benchmarks, very different, lots of different stuff that, you know, you can run to see how fast
your interpreter is. And we run that in Cython, and the problem with that is that the applications that have been tested there, they are a bit outdated, okay, and many of them were written in a pre-Python 2.6 area, and that means they don't use
many of the, so any of the more recent Python features. So it's a nice benchmark, but it's not very telling for any recent application that you would write. So in that benchmark series, we're currently about 1.3 to 3 times, depending on the benchmark,
faster than Python 3.5, and hand-tuning those benchmarks a little to make Cython generate better code for them gives you something like four times to 50 times. And how do you do that? Well, static type declarations, so Cython is actually a
language that supports optional static typing, in addition to being Python, and so in your code, you can say, you can declare variables, for example, having a certain type, and that's
an extended syntax, which says cdef some type x for variable declaration, so that's extensions to Python language, which then are only understood by the Cython compiler, not by Python. What does that do? Well, once Cython sees
these declarations, it can drop your code from object operations into plain C code, okay, so when it knows that a variable has a C integer type, for example, it can say, okay, adding a value to the variable can be done in C, don't need to wrap any object, so that's faster. And the nice thing, it says optional typing,
so you can employ these type declarations exactly where performance matters, and that's the way we made these benchmarks way faster than what you'd get from simply compiling the Python code. Especially from computational loops, usually the speedup you get is somewhere
between 100 and 1,000 times. Okay, the actual topic of today's talk is talking to native code, so I won't talk much about speedups, I will talk more about how do you connect to external libraries, how do you talk to them, how do you use C from
Python. So, since Cython code translates to C code, talking to native code or external code, external code written in C++ is actually completely natural, it's totally straightforward, and so that makes Cython a foreign function interface, but the cool way. You can think
of it as Python with C data types, and the nice thing that the compiler gives you is that these types convert back and forth from Python objects automatically for you. Cython understands pretty much all C data types, and most of C++ own data types,
that includes C functions, pointers, structs, arrays, and so on, and C++ classes, templates, operator overloading, and so on and so forth. Okay, and that's the end of the first part,
and here's the demo. First of all, C features. Who does not know the iPython notebook or the Jupyter notebook? Okay, everyone does, that's cool. So, in case there's someone here who's been working on it, who's been contributing to the code base,
thank you everyone, it's a great tool, it's wonderful, and has Cython support, so all you really have to do is you open a Python notebook, and then you say load x Cython, which enables Cython support, and currently, as you can see, I'm using Python 3.5 and
Cython 0.23 beta 1, so new 3s, and so here's an example. This is what you can see what a Cython code looks like, so I start my cell here with double percent Cython, which tells the Jupyter notebook that here's the Cython cell, and please compile this
for me, and then run it, and I can compile it, and it just works, and what I did here is I defined one little Python function. I defined a Python function with a typed argument, so the argument that's been accepted must be a C int, that's what I declared here. Then
I have one function here, which is a C def function, which translates into a plain C function, and then the last thing I have here is a C P def function, which is kind of a C function with a Python wrapper, so the Python wrapper is automatically generated
for you, and now I can call my Python function, which does what I want. I can call the Python function, which does the same thing, with difference that if I pass in something else than an int, ABC for example, then I get a type error, okay, and I get it on entry,
so it automatically checks for me when calling the function. Okay, then I can try to call the C function, and I'll see if there's a name error, so the C function doesn't actually appear at the module interface, because it's a C function, right, it's not a Python function, but what I can call is the C P def function, which then finally
calls the C function, and that's, as I said, a C function with a wrapper around it, so the wrapper becomes visible to Python code. Okay, a bit of function JIT compiling. We have a decorator called Cython compile, so this, not a Cython cell, it's a Python
cell, and you can import the Cython module and decorate a function, a Python function with a decorator, and then run that, and when you call the function, it executes, the result is down here, it executes the compile function for you, and you can see
that because Coq is not just a Python function, it's a runtime compile function. Okay? That's how you can do, you know, runtime compilation from, within Python. Okay, calling
C functions, as I said, it's entirely natural for Cython code to talk to C libraries, and the way this works is, well, we have a standard of, a couple of standard declarations that we ship that includes a large part of libc, libc++, the C Python, C API, so lots
of C functions that you can simply import, use, done, so the way it works in Cython is you say, from libc, so the libc library, there's a module in there called math, so the math header, from libc, C import math, and then you have access to the libc math
functions, and you can say math sine of pi by two, run that, and it will give you one. Okay? One nice thing you can see here is I didn't just say percent percent, Cython, I said Cython minus A, and minus A means annotate, and what I get out of it is an
annotated HTML version of my source code, and that allows me to see what Cython made of my source code, okay, because now here you can see exactly the source code as you saw above, but when I click on the line with the plus here in front, it'll show
me the C code that it generated for it, okay? So I can see, so what it does here is it does the computation pi by two, calls the C sine function on it, then calls the
double, C double result to a Python float object, and then calls a helper function which prints the result, because that's what it said here, right, prints the result of sine, okay? The reason why it's a bit yellow compared to the other lines is that there's interaction with Python going on, so there's actual Python object operations
here. As you can see, the result is calculated in C, but then afterwards I create a Python object from it and call the print function, and that's everything that, you know, adds up to the darkness of the yellow line here. So it's pretty dark, meaning quite an intensive
Python operation going on, okay? Memory allocation, same thing. We have the standard lib headers readily declared for you, so you can just say from lib C, standard lib C, import
malloc and free, and then you can call malloc, you have to check the results obviously if it's null, raise a memory error if it is, in other words, in this case we just free it, okay? Works for me. Okay, what you should do though, especially for little amounts of memory that you need, is use the C Python heap memory management, because that's
pre-advocated memory, so it doesn't have to talk to the operating system, and it's faster for small memory areas. So what I'm doing here is I replaced a malloc by py-malloc, same thing, check the results, and here I'm assigning some values to the
memory buffer that I allocated, and then do a little computation, print the results, and free the memory, okay? Important here, try finally, because even if something goes wrong here, I want to be sure that I free my memory. Up, execute it, it gives me four,
so it's adding up one and three, okay? Okay, one nice little feature that came in in 0.22, I think, so last release Python version, is automatic wrapping of C functions.
So here I'm C importing the math and standard lib modules from libc, and take this sine and a to i function, that's actual C functions, and assign them to Python variables, okay? Which makes them objects. So I can execute that, and you can look up what it does.
So here, it actually calls a helper function that it generated for me, which takes the C sine function, and wraps it in a Python callable for me, okay? And then it just adds it to the global module dictionary, so that it becomes available to Python code.
And then I can just call it from Python code, okay? So Python of half, apparently this, and I can take the a to i function, pass in the byte string, and it's one, two, three, okay? As a number. Okay? It's actually as simple as that. Okay, external libraries,
here's a bit more of an involved example, because what, so talking to libc is nice, but it doesn't usually get you very far, okay? So there are lots of helper functions in libc, but what you normally do is, so you want to talk to your own code, okay?
So you have some C code lying around, or an external library that you want to wrap, that you want to make available for Python, use it from your Python code, and so this is how this works. So I chose Lua, because I've also written a Lua wrapper for Python, which is called Luca, and so I happily copied some code from it for this presentation,
so there's a Lua header file, and I copied some declarations from it, which is a state, so that holds the runtime state of the Lua runtime, I can create a new Lua runtime,
as a function for closing the Lua runtime, so for cleaning up, and I can load code into the runtime, execute it, and then, so Lua is a stack machine, so I have some function to operate as a stack, and to call a function on it, and stuff, so that's all the declarations that are needed, important bit here is, it's not complete, so the Lua header file
is definitely way larger than what I've copied here, but that's all I needed, okay? And that's all that's Titan needs to know. And once that's declared, I can actually just use it, okay? So here's a function, run Lua, Python function, and I pass some Lua code in there, and then, first thing I do, I convert, make sure it's a byte
string, so I convert it to GFA, if it's Unicode, create a new Lua runtime, raise an error if that fails, load the code into Lua, raise a syntax error if that fails, because that's activating the Lua parser, and then get a result from that, call it,
execute the Lua code, if that fails, I just raise the runtime error, saying, you know, your code was broken, please try again, and then, the very simple return value conversion, so I'm expecting a Lua number back, raise an exception if it's,
happens to be not a number, otherwise I just convert it, so there's a helper function for converting the Lua number back to a C number, and then I return it. Okay, so that's all I need to execute Lua code in Python, in Python in this case, to make it available for calls from Python, okay? Again, try finally, so there's
a bit of cleanup, after creating the runtime, the Lua runtime, I need to make sure that I properly clean up afterwards, regardless of what happens, so any exceptions should leave memory leak or something, leave the runtime in memory, so I'll just clean everything up afterwards, and then I'm done. Okay? So, one thing I'm doing here, now
I take some Lua code, and pass it into the function, and at the end, I just say, I just, so I create a function, a Lua function, and then I call it in the end, and return the result, did I execute that? I didn't, okay, not executing that,
executing that, and it gives me the 10th Fibonacci number, apparently, so it's a recursive version of Fibonacci, and I can benchmark that, that's going to give me about five milliseconds, and the thing I didn't mention is, why does this actually
work, right? So, I'm using Lua code, but I'm not linking against it, yes I am, so what I'm saying about here is, when this compiles in this details, and I'm creating my shared library for Python, please use this include here to find the header file,
use these libraries to link against, okay, so I'm specifying that directly in my module, and now I linked against Lua 5.1, and now if I replace that by Lua JIT, which I also have installed, all I have to do is replace the include directory, so for fun I'm just
going to do that directly in my source code, I could also do that in my set up file, but since I have an iPad and notebook, I'm just going to do it in place, compile again, run the code again, same result, and it should be a bit faster now, yeah it's
about twice as fast, okay, just replacing the Lua implementation, okay what else do we have? A little bit of nice syntax, C arrays, so C arrays are actually quite clumsy in C, because they're basically just pointers, and sometimes C knows the length
a bit, doesn't really care about them, so Cython knows the length of a C array, and it has better ways to deal with them, so what I'm doing here is I'm creating two C arrays of integers length 10, A and B, and then I'm assigning to a slice, so I'm saying I have five values on the right, and I'm assigning that to a partial slice
of the array, the C array, then one nice feature is I can assign by value, so C doesn't care about the multiple, it's just going to assign the pointers, well it's actually going to give you an error, and say you can't assign arrays, so Cython does array
copying for you, so it assigns by value, very nice feature, and then I'm just assigning to the other half of the array a couple of more numbers, I can just iterate over the array by slicing it, I could iterate over the whole array by just saying for I and B, here I'm just interested in the first three numbers, so I'm iterating
over those, printing those, I just won in this case, and then I'm returning B, so what you see here, so I created a function for it, okay so this is all I do, and you see the iteration actually uses a C loop over the array, then we have here the assignment,
which just translates to a mem copy, pretty straightforward code, the assignment, the temporary array, and the mem copy, so this is all stuff that Cython does behind your back and it just does it right, then when I call my function, you see the iteration
here, two, three, four, so iterating over the first three values, and then when I'm returning the array, it automatically translates to Python list, and I get the mapped Python object as a return result, okay, I'm going to split that, and I'm just going to show
you a bit of C++, because you may not like C++, and there are lots of people who don't like C++, but it's actually really nice when used from Cython, and that's the only way I would ever use it, okay, so same thing here, load as Cython, same Cython
version I'm using, and now first I have to tell Cython that this is supposed to be compiled in C++ mode, which enables all sorts of C++ features, meaning operator overloading, meaning class support, templates, and so on, and as I said, we ship declarations
with Cython, that includes libc++, including for example what I'm using here, the vector class, so I can just say from libccp vector, C import the vector class, and here I'm defining the Python function, with a stack allocated C++ vector object, and then I can just insert
a value, there's a pushback method, whoever came up with that name, on a C++ vector class, and then I return it, what do you think that returns?
Someone's saying segfault down there, nope, because that's not what it does, it returns a list, okay, so there's a say for mapping from a C++ vector to Python list, so whenever you make Cython convert a C++ vector or a C++ list for you, any container it knows,
it'll just convert you to a list for you, or to a C++ map to Python dict, and so on, so you get the obvious representation in Python as default, okay?
Another little example, a vector, so the nice thing here is that Cython does the automatic memory management for you, so this is a stack allocated C++ vector, meaning it goes out of scope and dies, okay? All handled.
You can do the same thing with an extension type, so this is the way Cython defines extension types, anyone implemented an extension type with a C API? Okay, a couple of people, what you do basically is you take an existing extension type, copy over all that it has, because there's a model C code, it's all struct
definitions and stuff, and then you adapt it for your needs, because you're never gonna infer that, the way this works from the documentation, okay, so you just copy it over, adapt it. In Cython, you don't need to do that, okay, you just say cdef class and it's done, okay, you have an extension type.
Here I'm adding a field, so an attribute to the extension type, to the object in this case, which is a C++ vector, and that makes, and that ties the memory management for the C++ type to the lifetime of the Python object, so when the object's created, it
creates a C++ vector for you, and when the object dies, it will clean it up for you, okay? Okay. So there's an add method, which is called pushback and representation, and so I can execute that, and then the wrapper is actually just implemented as wrapper of the use of
the C++ vector, and when I execute this, as you can see, the representation of the class becomes a list, because that's the representation of the C++ vector converted to Python object, okay, so just use wrapper of list, and that's what you get.
Okay, okay, I'll just leave it at that, and yep, continue that over here. So conclusion, Cython is a tool for translating Python code to efficiency, and it's very easy
to interface with external native code, as you've seen, you just write the code and it just works. You can use it to speed up existing Python modules by concentrating on the optimization rather than a complete rewrite, which you have to write it in C, avoid writing C, just do it in Cython, it allows you to write C extensions for C Python in actual
Python syntax, using Python semantics, using Python language features, so it allows you to write C code without actually writing any C code at all, and you can use it to wrap C++ or C or C++ libraries in Python syntax just by, you know, using objects,
dealing with them, doesn't matter if it's Python object or C++ object, it looks all the same, feels the same, okay, thanks.
Thank you, Stefan, we have time for one question on my video, short questions, are there any questions? Down here? Yeah, okay, there, anyway. Hello, I was wondering, when calling C or C++ code from Cython, what is the
level of support for the new standards of C and C++? Four, what? For different standards of C++? C++, 11, so on and so forth. It depends on your C++ compiler, so Cython doesn't really care, I mean, it can be C++ 11, it can be C++ 19 or whatever there is, so just depends on your C++ compiler.
So, the question was, does it generate C code, C++ code, it depends, so it generates C code for almost everything except when you're interacting with C++ object, in which case you get C++ code for it, okay, so it knows about operators, for example, so,
you know, operator plus will translate into ASP, so you get C++ code for everything that C++ usage in your Python code. Okay, thank you. Thanks. Thank you.