{"id":16147950,"url":"https://github.com/alexf91/lean4-ctypes","last_synced_at":"2025-10-23T23:30:57.408Z","repository":{"id":205564998,"uuid":"687730346","full_name":"alexf91/lean4-ctypes","owner":"alexf91","description":"FFI for Lean 4","archived":true,"fork":false,"pushed_at":"2023-12-27T03:59:13.000Z","size":401,"stargazers_count":3,"open_issues_count":5,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-27T19:58:18.404Z","etag":null,"topics":["ffi","lean","lean4"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alexf91.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-09-05T22:19:39.000Z","updated_at":"2024-06-14T09:00:34.000Z","dependencies_parsed_at":"2023-12-27T04:54:54.784Z","dependency_job_id":"ff277079-a008-4566-bf12-106b6554bb43","html_url":"https://github.com/alexf91/lean4-ctypes","commit_stats":null,"previous_names":["alexf91/lean4-ctypes"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexf91%2Flean4-ctypes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexf91%2Flean4-ctypes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexf91%2Flean4-ctypes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexf91%2Flean4-ctypes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexf91","download_url":"https://codeload.github.com/alexf91/lean4-ctypes/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237893812,"owners_count":19383110,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ffi","lean","lean4"],"created_at":"2024-10-10T00:29:01.723Z","updated_at":"2025-10-23T23:30:52.126Z","avatar_url":"https://github.com/alexf91.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CTypes for Lean 4\n\nCTypes is a foreign function library for Lean 4, inspired by Python's [ctypes](https://docs.python.org/3/library/ctypes.html) module.\nIt provides C compatible data types, and allows calling functions in shared libraries. It can be used to wrap these libraries in pure Lean 4.\n\n## Usage\n\nLibrary functions are accessed through the `Library` type.\nIt is a wrapper around `dlopen()` for loading a shared library and `dlsym()` for looking up a symbol.\n\nThe `CType` type represents types available in C.\nIt contains definitions for signed and unsigned integers, floating point types, complex types, structs and pointers.\n\nValues are represented with the `CValue` type.\nIt directly matches the `CType` type, but also contains a value.\n\nThe low-level implementation is in the `CTypes.Core` namespace and implements basic types and function calls.\nIt is a wrapper around `libffi`.\n\n### Basic concepts\n\nThis example calls the function `pow()` in the library `libm.so.6`:\n\n```Lean\nimport CTypes\nopen CTypes.Core\n\ndef main (_ : List String) : IO UInt32 := do\n  -- Open the library. See man page for dlopen() for flags.\n  let lib ← Library.mk \"libm.so.6\" .RTLD_NOW #[]\n\n  -- Lookup the symbol `pow`.\n  -- As an alternative `libm[\"pow\"]` can be used.\n  let pow ← lib.symbol \"pow\"\n\n  -- Call the function with two regular `CValue` objects and no variadic arguments.\n  let result ← pow.call .double #[.double 1.4142, .double 2.0] #[]\n\n  -- The result has type `CType.double`.\n  IO.println s!\"result: {repr result}\"\n\n  return 0\n```\n\n### Pointers\n\nWhile equivalents to basic C types exist in Lean, this is not the case for pointers.\nThe `Pointer` type is used to access raw memory from Lean.\nThey support pointer arithmetic and dereferencing.\n\nUnless noted otherwise, the library will never allocate or free memory on its own.\nThis has to be done by the user with `malloc()`, `free()` and similar functions.\n\n```Lean\nimport CTypes\nopen CTypes.Core\n\ndef main (_ : List String) : IO UInt32 := do\n  let lib ← Library.mk \"libc.so.6\" .RTLD_NOW #[]\n  let malloc ← lib[\"malloc\"]\n  let free   ← lib[\"free\"]\n\n  -- Allocate a `int16_t` buffer.\n  let p ← malloc.call .pointer #[.size_t CType.int16.size] #[]\n  -- Write the value.\n  p.pointer!.write (.int16 42)\n  -- Read back the value.\n  let value ← p.pointer!.read .int16\n\n  IO.println s!\"value: {repr value}\"\n  -- Free the allocated buffer.\n  discard \u003c| free.call .void #[p] #[]\n\n  return 0\n```\n\n### Callbacks\n\nLean functions can be called from C by creating a `Closure` object.\nPointers to the closure can be passed to C functions or called like regular function pointers.\n\n```Lean\nimport CTypes\nopen CTypes.Core\n\ndef main (_ : List String) : IO UInt32 := do\n  -- Callback functions have the signature (Array CValue) → IO CValue\n  let add : Callback := fun args =\u003e do\n    return .int (args[0]!.int! + args[1]!.int!)\n\n  -- Create the closure.\n  let closure ← Closure.mk .int #[.int, .int] add\n\n  -- Call the function through the `Pointer.call` interface.\n  let result ← closure.pointer.call .int #[.int 42, .int 11] #[]\n  IO.println s!\"42 + 11 = {result.int!}\"\n\n  -- Closures are not deleted by default, in case a C function stores a reference.\n  -- They have to be marked for deletion by the user.\n  -- Deleted closures are freed when the object is garbage collected. Otherwise they\n  -- leak memory.\n  closure.delete\n\n  return 0\n```\n\n### Structs and arrays\n\nStructs are described as an array of types and instantiated as an array of values.\nThere is no direct support for arrays in the `CTypes.Core` library.\nIf arrays should be passed to functions, then the buffer has to be allocated with `malloc()`.\nIf an array is a member of a struct, then the array can created with a struct with one value for each array element.\n\nArrays created this way can not be passed to functions.\n\nHere is an example that uses callbacks and a pointer to a struct to calculate the Fibonacci sequence:\n\n```Lean\nimport CTypes\nopen CTypes.Core\n\ndef main (_ : List String) : IO UInt32 := do\n  -- Fibonacci iteration with a struct as state variable.\n  let fib : Callback := fun args =\u003e do\n    let state ← args[0]!.pointer!.read $ .struct #[.int, .int]\n\n    -- Get the two values from the (int, int) struct.\n    let a := state.struct![0]!.int!\n    let b := state.struct![1]!.int!\n\n    -- Update the values and return the result.\n    args[0]!.pointer!.write (.struct #[.int b, .int (a + b)])\n    return .int a\n\n  -- The closure object for the C function.\n  let closure ← Closure.mk .int #[.pointer] fib\n\n  -- Initialize the state struct to (0, 1).\n  let libc ← Library.mk \"libc.so.6\" .RTLD_NOW #[]\n  let state ← (← libc[\"malloc\"]).call .pointer #[.size_t (CType.struct #[.int, .int]).size] #[]\n  state.pointer!.write $ .struct #[.int 0, .int 1]\n\n  for _ in [0:8] do\n    let result ← closure.pointer.call .int #[state] #[]\n    IO.println $ repr result\n\n  -- Cleanup\n  closure.delete\n  discard \u003c| (← libc[\"free\"]).call .void #[state] #[]\n\n  return 0\n```\n\n## Build instructions\n\nBuilding the library is still experimental and requires that the same compiler is used for code generated by the Lean compiler and the C++ files in `src/`.\nThis requires setting `LEAN_CC` when `lake` is called: `LEAN_CC=clang++ lake build`.\nOnly Linux systems and the `clang++` compiler are currently supported.\n\nTests can be executed with `LEAN_CC=clang++ lake exe tests`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexf91%2Flean4-ctypes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexf91%2Flean4-ctypes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexf91%2Flean4-ctypes/lists"}