import ctypes
import os
import platform
import sys
from ctypes import c_uint8, c_uint64, c_void_p
from pathlib import Path
def _find_lib():
bridge_dir = Path(__file__).resolve().parent.parent / "rust_bridge" / "target" / "debug"
if platform.system() == "Darwin":
return bridge_dir / "libffi_bridge.dylib"
return bridge_dir / "libffi_bridge.so"
lib = ctypes.CDLL(str(_find_lib()))
class FfiPollResult(ctypes.Structure):
_fields_ = [
("ready", c_uint8),
("_padding", c_uint8 * 7),
("value", c_uint64),
]
lib.counter_new.argtypes = [c_uint64]
lib.counter_new.restype = c_void_p
lib.counter_free.argtypes = [c_void_p]
lib.counter_free.restype = None
lib.counter_next_value.argtypes = [c_void_p]
lib.counter_next_value.restype = c_void_p
lib.counter_add.argtypes = [c_void_p, c_uint64]
lib.counter_add.restype = c_void_p
lib.future_poll.argtypes = [c_void_p]
lib.future_poll.restype = FfiPollResult
lib.future_free.argtypes = [c_void_p]
lib.future_free.restype = None
def poll(future_handle):
while True:
result = lib.future_poll(future_handle)
if result.ready != 0:
return result.value
passed = 0
failed = 0
def check(name, got, want):
global passed, failed
if got == want:
print(f" PASS {name}: got {got}")
passed += 1
else:
print(f" FAIL {name}: got {got}, want {want}")
failed += 1
def main():
global passed, failed
print("=== Python <-> Rust FFI (Sendable + PollOnce) e2e test ===")
print()
counter = lib.counter_new(10)
fut = lib.counter_next_value(counter)
val = poll(fut)
lib.future_free(fut)
check("next_value(10)", val, 11)
fut = lib.counter_add(counter, 32)
val = poll(fut)
lib.future_free(fut)
check("add(10, 32)", val, 42)
lib.counter_free(counter)
counter = lib.counter_new(100)
fut = lib.counter_next_value(counter)
val = poll(fut)
lib.future_free(fut)
check("next_value(100)", val, 101)
fut = lib.counter_add(counter, 900)
val = poll(fut)
lib.future_free(fut)
check("add(100, 900)", val, 1000)
lib.counter_free(counter)
print()
print(f"--- {passed} passed, {failed} failed ---")
if failed > 0:
sys.exit(1)
if __name__ == "__main__":
main()