Generating PHP extensions is now possible with https://github.com/openpeeps/clue 😂
Don't try to install via pkg manager (some nim files are missing), clone it instead.
phpModule do:
name = "hello"
version = "0.1.0"
proc helloWorld(name: string) =
echo "👋 Hey there ", name, " 👑 Nim is Awesome!"
Use -d:clueDebugExtension to inspect the generated Nim code
var moduleEntry {.inject.}: ptr zend_module_entry
var functionEntry {.inject.}: ptr zend_function_entry
proc nim_module_init(typ {.inject.}: cint; module_number {.inject.}: cint): cint {.
cdecl.} =
phpclue_zend_result_success()
proc helloWorld(ctx: ptr zend_execute_data; retTy: ptr zval): void {.cdecl.} =
var name: cstring = nil
var nameLen: csize_t = 0
if phpclue_zend_parse_parameters(ctx, "s", addr(name), addr(nameLen)) !=
phpclue_zend_result_success():
phpclue_throw_type_error(("$1: Argument 1 passed must be of type string" %
["helloWorld"]))
return
echo "👋 Hey there ", name, " 👑 Nim is Awesome!"
proc phpclue_nim_module_entry*(): ptr zend_module_entry {.cdecl, exportc, dynlib.} =
## The main entry point for the PHP extension, which will be called by PHP
## when the extension is loaded.
var paramCheckArg_536870949 {.inject.} = phpclue_arginfo_alloc(1.csize_t)
phpclue_arginfo_set_typed(paramCheckArg_536870949, 0, false, "name",
phpclue_get_IS_STRING(), false)
paramCheckArg_536870949 = phpclue_arginfo_finalize(paramCheckArg_536870949,
1.csize_t)
functionEntry = phpclue_fe_alloc(csize_t(2))
phpclue_fe_set(functionEntry, csize_t(0), "helloWorld", helloWorld,
paramCheckArg_536870949, 0'u32, 0'u32)
phpclue_fe_end(functionEntry, csize_t(2))
moduleEntry = phpclue_module_alloc()
phpclue_module_init(m = moduleEntry, name = cstring("hello"),
version = cstring("0.1.0"), functionEntry,
nim_module_init, mshutdown = nil, rinit = nil,
rshutdown = nil, minfo = nil)
moduleEntry
Next on my todo list, add same DSL for generating N-API addons (via pkg/denim), python is next (pkg/nimpy), ruby and more, so basically jsModule do, rubyModule pyModule, and maybe a initModules template that can wrap all modules. Crazy!
An OpenAPI 3.0 parser in progress here https://github.com/openpeeps/clue/tree/main/src/clue/openapi. Also, there are many ideas on the table, check it here https://github.com/openpeeps/clue#-key-features
import clue/kits/luakit
luaModule do:
name: "mylib"
proc hello(name: string) =
lua_pushstring(L, cstring("Hello " & name & " from Nim!"))
return 1
proc add(a: int, b: int) =
lua_pushinteger(L, a + b)
return 1
import clue/kits/rubykit
rubyModule do:
name: "Example"
version: "0.1.0"
proc hello(name: string) =
echo "Hello ", name, " from Nim!"
proc add(a: int, b: int) =
result = INT2NUM(cint(a + b))
import clue/kits/pykit
pythonModule do:
name: "mylib"
proc hello(name: string) =
result = PyUnicode_FromString(cstring("Hello " & name & " from Nim!"))
proc add(a: int, b: int) =
result = PyLong_FromLong(a + b)
There is stil room for improvements (like a better, unified API for data types).
For a real implementation, check Tim Engine's main tim.nim module here, where I'm using the static when defined to determine the build type while exposing some Tim Engine API.
Huge update! Clue CLI is capable to generate Nim code from OpenAPI 3.0. Currently, the generated code is still low-quality but, once done it will be able generate packages via cli, eventually via a GH runner, scheduled, so it can check for updates and generate, commit, push, release. We need search engines/LLM bots to be able to scan generated clients, wrappers and so on
I keep my eyes on https://github.com/nimlibs (love the name, but is pretty abandoned), I just asked James, the original owner to give me permission to the org here: https://github.com/nimlibs/simdX86/issues/2. The idea is to have a trusty place where we can use Clue's OAPI generator, a place where many of us can be part of the organization. Anyone, any other org instead of nimlibs (in case James is not at home lol).
The juice. https://github.com/openpeeps/clue