Skip to content

Instantly share code, notes, and snippets.

@yudhastyawan
Created May 24, 2021 12:49
Show Gist options
  • Save yudhastyawan/dc9aba18a64823500d7dc1110380d5be to your computer and use it in GitHub Desktop.
Save yudhastyawan/dc9aba18a64823500d7dc1110380d5be to your computer and use it in GitHub Desktop.
embed Fortran in Python using Cython
module penjumlahan_interface
use iso_c_binding, only: c_double
use penjumlahan_module, only: penjumlahan
implicit none
contains
subroutine c_penjumlahan(a, b, c) bind(c)
real(c_double), intent(in) :: a, b
real(c_double), intent(out) :: c
call penjumlahan(a, b, c)
end subroutine c_penjumlahan
end module penjumlahan_interface
extern void c_penjumlahan(double* a, double* b, double* c);
module perkalian_interface
use iso_c_binding, only: c_double
use perkalian_module, only: perkalian
implicit none
contains
subroutine c_perkalian(a, b, c) bind(c)
real(c_double), intent(in) :: a, b
real(c_double), intent(out) :: c
call perkalian(a, b, c)
end subroutine c_perkalian
end module perkalian_interface
extern void c_perkalian(double* a, double* b, double* c);
module penjumlahan_module
implicit none
contains
subroutine penjumlahan(a, b, c)
double precision, intent(in) :: a, b
double precision, intent(out) :: c
c = a + b
end subroutine penjumlahan
end module penjumlahan_module
module perkalian_module
implicit none
contains
subroutine perkalian(a, b, c)
double precision, intent(in) :: a, b
double precision, intent(out) :: c
c = a * b
end subroutine perkalian
end module perkalian_module
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
# This line only needed if building with NumPy in Cython file.
from numpy import get_include
from os import system
# HOW TO RUN SETUP.PY
# python setup.py build_ext -inplace --plat-name=win-amd64
# python setup.py install
def fortran_compiler(statement):
print(statement)
system(statement)
# compile the fortran modules without linking
# compile fortran modules
fortran_compiler('gfortran penjumlahan.f90 -c -o penjumlahan.o -O3 -fPIC')
fortran_compiler('gfortran perkalian.f90 -c -o perkalian.o -O3 -fPIC')
# compile fortran shared modules
fortran_compiler('gfortran c_penjumlahan.f90 -c -o c_penjumlahan.o -O3 -fPIC')
fortran_compiler('gfortran c_perkalian.f90 -c -o c_perkalian.o -O3 -fPIC')
# editable components
module_name = "kalkulator"
source_file = "source_file.pyx"
compiled_modules = ['penjumlahan.o', 'perkalian.o', 'c_penjumlahan.o', 'c_perkalian.o']
# setup
ext_modules = [Extension(# module name:
module_name,
# source file:
[source_file],
# other compile args for gcc
extra_compile_args=['-fPIC', '-O3'],
# other files to link to
extra_link_args=compiled_modules)]
for e in ext_modules:
e.cython_directives = {'language_level': "3"} #all are Python-3
setup(name = module_name,
cmdclass = {'build_ext': build_ext},
# Needed if building with NumPy.
# This includes the NumPy headers when compiling.
include_dirs = [get_include()],
ext_modules = ext_modules)
cdef extern from "c_penjumlahan.h":
void c_penjumlahan(double* a, double* b, double* c)
cdef extern from "c_perkalian.h":
void c_perkalian(double* a, double* b, double* c)
def penjumlahan(double a, double b):
cdef:
double c
c_penjumlahan(&a, &b, &c)
return c
def perkalian(double a, double b):
cdef:
double c
c_perkalian(&a, &b, &c)
return c
@yudhastyawan
Copy link
Author

yudhastyawan commented May 24, 2021

How to run setup.py

python setup.py build_ext -inplace --plat-name=win-amd64
python setup.py install

Requirements for Windows:

  1. minGW-w64 (download)
  2. (optional case) if this statement is out on cmd error: Unable to find vcvarsall.bat then the computer need to install Visual Studio (download). During the installation, select the Python development workload and the Native development tools option.

Personal:
Python version: 3.8.10
Conda version: 4.9.2
OS: Windows 10 Pro ver. 10.0.19042 Build 19042

@yudhastyawan
Copy link
Author

yudhastyawan commented May 24, 2021

The Example

(base) C:\go\to\directory>python
>>> import kalkulator
>>> kalkulator.penjumlahan(3,5)
8.0
>>> kalkulator.perkalian(3,5)
15.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment