From a80f042f3503ae78e558028b38175ea3ae8d61c9 Mon Sep 17 00:00:00 2001 From: Ivan FB Date: Sun, 3 May 2026 16:36:37 +0200 Subject: [PATCH] use proper case --- examples/nim_timer/nim_timer.nim | 8 ++++---- ffi/internal/ffi_macro.nim | 23 +++++++++++++++++------ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/examples/nim_timer/nim_timer.nim b/examples/nim_timer/nim_timer.nim index a9f0329..e595cf6 100644 --- a/examples/nim_timer/nim_timer.nim +++ b/examples/nim_timer/nim_timer.nim @@ -33,7 +33,7 @@ type ComplexResponse {.ffi.} = object # --- Constructor ----------------------------------------------------------- # Called once from Rust. Creates the FFIContext + NimTimer. # Uses chronos (await sleepAsync) so the body is async. -proc nimtimer_create*( +proc nimtimerCreate*( config: TimerConfig ): Future[Result[NimTimer, string]] {.ffiCtor.} = await sleepAsync(1.milliseconds) # proves chronos is live on the FFI thread @@ -42,7 +42,7 @@ proc nimtimer_create*( # --- Async method ---------------------------------------------------------- # Waits `delayMs` milliseconds (non-blocking, on the chronos event loop) # then echoes the message back with a request counter. -proc nimtimer_echo*( +proc nimtimerEcho*( timer: NimTimer, req: EchoRequest ): Future[Result[EchoResponse, string]] {.ffi.} = await sleepAsync(req.delayMs.milliseconds) @@ -51,10 +51,10 @@ proc nimtimer_echo*( # --- Sync method ----------------------------------------------------------- # No await — the macro detects this and fires the callback inline, # without going through the request channel. -proc nimtimer_version*(timer: NimTimer): Future[Result[string, string]] {.ffi.} = +proc nimtimerVersion*(timer: NimTimer): Future[Result[string, string]] {.ffi.} = return ok("nim-timer v0.1.0") -proc nimtimer_complex*( +proc nimtimerComplex*( timer: NimTimer, req: ComplexRequest ): Future[Result[ComplexResponse, string]] {.ffi.} = let note = if req.note.isSome: req.note.get else: "" diff --git a/ffi/internal/ffi_macro.nim b/ffi/internal/ffi_macro.nim index fadbcee..6f4203e 100644 --- a/ffi/internal/ffi_macro.nim +++ b/ffi/internal/ffi_macro.nim @@ -10,6 +10,15 @@ when defined(ffiGenBindings): # String helpers used by multiple macros # --------------------------------------------------------------------------- +proc nimNameToCExport(s: string): string = + ## Converts a camelCase Nim proc name to a snake_case C export name. + ## Leaves already-snake_case names unchanged. + ## e.g. "nimtimerCreate" → "nimtimer_create", "nimtimer_echo" → "nimtimer_echo" + for i, c in s: + if c.isUpperAscii() and i > 0: + result.add('_') + result.add(c.toLowerAscii()) + proc registerFfiTypeInfo(typeDef: NimNode): NimNode {.compileTime.} = ## Registers the type in ffiTypeRegistry for binding generation and returns ## the clean typeDef. Serialization is handled by the generic overloads in serial.nim. @@ -657,6 +666,7 @@ macro ffi*(prc: untyped): untyped = raw[0 ..^ 2] else: raw + let cExportName = nimNameToCExport(procNameStr) let camelName = toCamelCase(procNameStr) # Names of generated things @@ -808,7 +818,7 @@ macro ffi*(prc: untyped): untyped = pragmas = newTree( nnkPragma, ident("dynlib"), - ident("exportc"), + newTree(nnkExprColonExpr, ident("exportc"), newStrLitNode(cExportName)), ident("cdecl"), newTree(nnkExprColonExpr, ident("raises"), newTree(nnkBracket)), ), @@ -839,7 +849,7 @@ macro ffi*(prc: untyped): untyped = retTn = $retTypeInner ffiProcRegistry.add( FFIProcMeta( - procName: procNameStr, + procName: cExportName, libName: currentLibName, kind: ffiFfiKind, libTypeName: $libTypeName, @@ -937,7 +947,7 @@ macro ffi*(prc: untyped): untyped = pragmas = newTree( nnkPragma, ident("dynlib"), - ident("exportc"), + newTree(nnkExprColonExpr, ident("exportc"), newStrLitNode(cExportName)), ident("cdecl"), newTree(nnkExprColonExpr, ident("raises"), newTree(nnkBracket)), ), @@ -968,7 +978,7 @@ macro ffi*(prc: untyped): untyped = retTnSync = $retTypeInnerSync ffiProcRegistry.add( FFIProcMeta( - procName: procNameStr, + procName: cExportName, libName: currentLibName, kind: ffiFfiKind, libTypeName: $libTypeName, @@ -1304,6 +1314,7 @@ macro ffiCtor*(prc: untyped): untyped = procNameStr[0 ..^ 2] else: procNameStr + let cExportName = nimNameToCExport(cleanName) let reqTypeNameStr = toCamelCase(cleanName) & "CtorReq" let reqTypeName = ident(reqTypeNameStr) @@ -1403,7 +1414,7 @@ macro ffiCtor*(prc: untyped): untyped = pragmas = newTree( nnkPragma, ident("dynlib"), - ident("exportc"), + newTree(nnkExprColonExpr, ident("exportc"), newStrLitNode(cExportName)), ident("cdecl"), newTree(nnkExprColonExpr, ident("raises"), newTree(nnkBracket)), ), @@ -1424,7 +1435,7 @@ macro ffiCtor*(prc: untyped): untyped = ctorExtraParams.add(FFIParamMeta(name: paramNames[i], typeName: tn, isPtr: isPtr)) ffiProcRegistry.add( FFIProcMeta( - procName: cleanName, + procName: cExportName, libName: currentLibName, kind: ffiCtorKind, libTypeName: $libTypeName,