interoptopus_backend_cpython_cffi 0.13.8

Generates CPython CFFI bindings.
Documentation
import ctypes
import reference_project as r
from reference_project import api
import time

N = 1_000_000

r.init_api("../../../../target/debug/interoptopus_reference_project.dll")

def bench(file, name, f, reference=0):
    start = time.perf_counter()

    for i in range(N):
        f()

    end = time.perf_counter()
    nanos = (end - start) * 1000 * 1000 * 1000
    nanos_per_single = (nanos / N) - reference

    name = f"`{name}`"
    print("|", name.ljust(50), "| {:,.0f} |".format(nanos_per_single), file=file)
    return nanos_per_single


# ptr = (ctypes.c_int64 * 100)(100, 2, 3)
# empty = r.Empty.c_array(1)


with open("BENCHMARK_RESULTS.md", 'w') as f:
    print("""

# FFI Call Overheads

The numbers below are to help FFI design decisions by giving order-of-magnitude estimates how
expensive certain constructs are.

Times were determined by running the given construct 1M times, taking the elapsed time in ticks,
and computing the cost per 1k invocations.


## System

The following system was used:    

```
System: i9-9900K, 32 GB RAM; Windows 10
rustc: stable (i.e., 1.53 or later)
profile: --release
Python: 3.10
```

## Results

| Construct | ns per call |
| --- | --- |""", file=f)

    reference = bench(f, "empty", lambda: 0)
    bench(f, "primitive_void()", lambda: r.api.primitive_void(), reference)
    bench(f, "primitive_u8(0)", lambda: r.api.primitive_u8(0), reference)
    bench(f, "primitive_u16(0)", lambda: r.api.primitive_u16(0), reference)
    bench(f, "primitive_u32(0)", lambda: r.api.primitive_u32(0), reference)
    bench(f, "primitive_u64(0)", lambda: r.api.primitive_u64(0), reference)
    bench(f, "many_args_5(0, 0, 0, 0, 0)", lambda: r.api.many_args_5(0, 0, 0, 0, 0), reference)
    # bench(f, "ptr(x)", lambda: r.api.ptr(ptr), reference)
    bench(f, "tupled(r.Tupled())", lambda: r.api.tupled(r.Tupled()), reference)
    # bench(f, "complex_args_1(r.Vec3f32(), empty)", lambda: r.api.complex_args_1(r.Vec3f32(), empty), reference)
    bench(f, "callback(lambda x: x, 0)", lambda: r.api.callback(lambda x: x, 0), reference)
    # bench(f, "pattern_ffi_slice_delegate(lambda x: x[0])", lambda: r.api.pattern_ffi_slice_delegate(lambda x: x[0]),
    #       reference)
    # bench("pattern_ffi_slice_delegate_huge(lambda x: x[0])", lambda: r.pattern_ffi_slice_delegate_huge(lambda x: x[0]), reference) # ??