@@ -258,29 +258,33 @@ proc emitStructType(reg: var CTypeReg, t: FFITypeMeta) =
258258proc ensureCType (reg: var CTypeReg , t: FFIType ): tuple [cType: string , owns: bool ] =
259259 # # Walks the shared type IR into a C type, monomorphising each distinct
260260 # # `seq[T]` / `Option[T]` into its own struct + codec triple on first sight.
261+ # # `owns` marks a C type that carries heap-allocated payload the caller must
262+ # # release with its generated free function (strings, byte buffers, and any
263+ # # seq/opt/struct transitively containing one); plain scalars and pointers own
264+ # # nothing and need no cleanup.
261265 case t.kind
262266 of ftPtr:
263- (CPtrType , false )
267+ return (CPtrType , false )
264268 of ftScalar:
265- (scalarCInfoTable[t.scalar].cType, false )
269+ return (scalarCInfoTable[t.scalar].cType, false )
266270 of ftStr:
267- (" NimFfiStr" , true )
271+ return (" NimFfiStr" , true )
268272 of ftBytes:
269- (" NimFfiBytes" , true )
273+ return (" NimFfiBytes" , true )
270274 of ftSeq:
271275 let (elemC, _) = ensureCType (reg, t.elem)
272276 let name = reg.libType & " Seq_" & cToken (elemC)
273277 if name notin reg.emitted:
274278 reg.emitted.incl (name)
275279 emitSeqType (reg, name, elemC)
276- (name, true )
280+ return (name, true )
277281 of ftOpt:
278282 let (elemC, elemOwns) = ensureCType (reg, t.elem)
279283 let name = reg.libType & " Opt_" & cToken (elemC)
280284 if name notin reg.emitted:
281285 reg.emitted.incl (name)
282286 emitOptType (reg, name, elemC, elemOwns)
283- (name, reg.owns.getOrDefault (name, false ))
287+ return (name, reg.owns.getOrDefault (name, false ))
284288 of ftStruct:
285289 let name = t.name
286290 if name notin reg.emitted:
@@ -289,7 +293,7 @@ proc ensureCType(reg: var CTypeReg, t: FFIType): tuple[cType: string, owns: bool
289293 emitStructType (reg, reg.typeTable[name])
290294 else :
291295 reg.decls.add (" /* unknown type referenced: " & name & " */" )
292- (name, reg.owns.getOrDefault (name, false ))
296+ return (name, reg.owns.getOrDefault (name, false ))
293297
294298proc ensureCType (reg: var CTypeReg , nimType: string ): tuple [cType: string , owns: bool ] =
295299 ensureCType (reg, parseFFIType (nimType))
@@ -306,7 +310,9 @@ proc reqTypeMeta(p: FFIProcMeta): FFITypeMeta =
306310
307311func paramByValue (nimType: string , ridesAsPtr: bool ): bool =
308312 # # Scalars / opaque pointers / string views pass by value; composite
309- # # aggregates (seq, Option, user structs) pass by const pointer.
313+ # # aggregates (seq, Option, user structs) pass by const pointer. Note `ptr T`
314+ # # rides by value as the 64-bit wire int (like `pointer`); production params
315+ # # reach here as `pointer` since handles are pre-converted upstream.
310316 if ridesAsPtr:
311317 return true
312318 parseFFIType (nimType).kind in {ftScalar, ftStr, ftPtr}
0 commit comments