When I do some bindings, many times I end up wih someting like the folowing:
proc IsNormal*(this: gp_Vec, Other: gp_Vec, AngularTolerance: cdouble): bool {.importcpp: "IsNormal".}
What I do afterwards is to wrap it again like this:
proc isNormal*(this: gp_Vec, Other: gp_Vec, AngularTolerance: float): bool =
IsNormal(this, Other, AngularTolerance.cdouble)
I reuse most of the types, and I only replace cdouble (or equivalent) by float (or equivalent). Most of the code is repetitive.
How could I simplify this or is there something that I am doing wrong?
It would be nice something like:
proc isNormal*(this: gp_Vec, other: gp_Vec, angularTolerance: float): bool {.importcpp: "IsNormal", convert[AngularTolerance]:cdouble.}
But I don't know if this is feasible or if it makes sense at all.I dont think thats doable, but i would recommend you turning those second wraps into templates instead of procs.
And you could write a more or less simple macro (about 50 lines of code) to automate this if you really wanted to.
cdouble == float == float64 so it's unnecessary in this case.
Also to give you a start on @Recruit_main707 suggestion, here is an overloading macro that I use to transform c2nim generated proc for float32 and float64 under a single interface, for example:
proc foo_single(a: ptr cfloat, b: ptr cfloat){.importc: "foo_single".}
proc foo_double(a: ptr cdouble, b: ptr cdouble){.importc: "foo_double".}
and
overload(foo, foo_single)
overload(foo, foo_double)
will make use of Nim overloading to generate a common foo interface for both types:
import macros
# Alias / overload generator
# --------------------------------------------------------------------------------------
macro overload*(overloaded_name: untyped, lapack_name: typed{nkSym}): untyped =
let impl = lapack_name.getImpl()
impl.expectKind {nnkProcDef, nnkFuncDef}
# We can't just `result[0] = overloaded_name`
# as libName (lapack library) is not defined in this scope
var
params = @[newEmptyNode()] # No return value for all Lapack proc
body = newCall(lapack_name)
impl[3].expectKind nnkFormalParams
for idx in 1 ..< impl[3].len:
# Skip arg 0, the return type which is always empty
params.add impl[3][idx]
body.add impl[3][idx][0]
result = newProc(
name = overloaded_name,
params = params,
body = body,
procType = nnkTemplateDef
# pragmas = nnkPragma.newTree(ident"inline")
)
when false:
# View proc signature.
# Some procs like syevr have over 20 parameters
echo result.toStrLit
i would recommend you turning those second wraps into templates instead of procs.
I use the “inline” pragma for that. My intuition is that a template is overkill for this. (And templates don’t get type-checked when compiled, only called, which is annoying.) Or am I missing something?