First Wrapped Function

This example shows how to build a simple scalar Fortran function and call it from Python using the exact NumPy dtypes required by its contract.


Source Code

Create scale.f90:

real(8) function scale(value, factor) result(output)
  real(8), intent(in) :: value
  real(8), intent(in) :: factor
  output = value * factor
end function scale

Inspect the Generated Contract

Preview the Python interface before building:

python3 -m prik generate --pyi scale.f90

The generated semantic .pyi contains:

from prik.contracts import Addr, Arg, Float64, external, native_call

@external
@native_call([Addr(Arg(0)), Addr(Arg(1))])
def scale(
    value: Float64,
    factor: Float64
) -> Float64: ...

Float64 means the function requires numpy.float64 scalar arguments and returns the same scalar type. @external identifies a procedure outside a Fortran module. @native_call(...) maps the two Python arguments to the native call and passes each scalar by address.

This file is both the wrapper contract and an editable description of the Python interface. You can leave it unchanged for this example; later pages show useful edits in context.


Build the Extension

From the directory containing scale.f90, run:

python3 -m prik scale.f90 --out-dir build/first-function

This creates an importable scale extension module in the build/first-function directory.


Inspect the Generated Docstring

prik creates NumPy-style docstrings from the same contract. Import the built extension and inspect the function:

import sys

sys.path.insert(0, "build/first-function")
import scale

print(scale.scale.__doc__)
scale(value, factor) -> float64

Parameters
----------
value : float64
factor : float64

Returns
-------
result : float64

help(scale.scale) shows the same signature, parameter types, result, and documented exceptions. Generated modules, classes, methods, and properties also provide docstrings.


Call the Function

import numpy as np

result = scale.scale(np.float64(3.0), np.float64(2.5))
print(result)          # 7.5
assert result == 7.5

Common Pitfall: Wrong Scalar Type

You must pass the exact NumPy scalar types:

# This will raise TypeError
scale.scale(3.0, 2.5)

# Correct way
scale.scale(np.float64(3.0), np.float64(2.5))

Always convert at the call site for scalar arguments.


If the build fails, rerun it with --verbose.


Next