I am using varargs in the following example
proc igraphsmall*(graph: ptr igrapht; n: igraphintegert; directed: igraphboolt;
first: cint): igrapherrort {.cdecl, varargs,
importc: "igraph_small".}
How can I pass a seq[cint] to first?
I am starting to think that this is bug in Nim.
The following works:
proc example*(name:string; first: varargs[int]) =
echo name
echo first.len
echo first
example( "hola", 1, 2, 3, 4)
example( "hola", @[1,2,3,4])
I am playing with some bindings to igraph: igraph.nim. In this line I call newSmall. In this function, I create a tmp:seq[cint] that I try to pass to igraph_small in the last parameter. This is the igraph_small definition.
I would expect the varargs pragma to behave as a normal varargs. So, is this a bug in Nim or am I doing something wrong?
Unfortunately C varargs and Nim varargs are quite different from each other. C varargs are basically just a pointer to somewhere in memory and it's up to the callee to handle this collection of arbitrary data (typically done by C macros which will advance the pointer depending on the type you "took out" of the collection). Nim varargs can really only have one type and (I believe) is passed along as something more sequence like.
As another gotcha the varargs pragma take a variable number of parameters after the last specified parameter., so your two definitions does not mean the same thing. In order to create a runtime dynamic list compatible with va_list (the type used by C varargs) you have to pack the arguments into one contiguous region of memory (with the correct padding) and pass a pointer of that to the function. Of course if you're only looking for a one-of or to generate this call with a macro then simply defining an object with all your data in order should suffice.
But I understand that what the pragma does is precisely the difficult part, doesn't it?
I mean, the part that I am missing is something that converts this call:
igraph_small(xxx, ..., yy, @[1,2,3,4])
into:
igraph_small(xxx, ..., yy, 1, 2, 3, 4)
under the hood.According to the SWIG document in PMunch's posts, when you call C function with variable length arguments, the number of arguments as well are their types and sizes must be known for C compiler. So, you cannot pass a sequence to such a C function as variable length arguments because the length of sequence is unknown at compile time.
You need to manually expand seq like printf("%d, %d\n", myseq[0], myseq[1]) or find similar C function that takes a pointer to an array instead of variable length arguments. If the number of arguments you want to pass is known at compile time, you can put them in an array instead of a seq and use macro like this: https://demotomohiro.github.io/littlesugar/unpackToArgs.html https://github.com/demotomohiro/littlesugar/blob/main/src/littlesugar/unpackToArgs.nim
I mean, the part that I am missing is something that converts this call: ... into: ...
Well the real problem here is that C does not allow for this transformation at all.
If you are serious about using igraph from Nim (or another language), be aware that igraph has an interface generator which you could modify for this purpose: https://github.com/igraph/stimulus/ It wasn't advertised for general use, but it's currently being used to generate most of igraph's R interface, and will be used for the upcoming major refactor of its Python interface (see https://github.com/igraph/python-igraph-ctypes). It uses the interface description in this file, which contains more semantic information than what a barebones C prototype can. This approach, along with wrappers for basic datatypes (see C++ proof of concept) should be able to take you quite far.
you should simply be using igraph_create for this.
That sounds right. igraph_small() is specifically a C language convenience function, mostly intended for easier testing of C code.
Note: I don't know much about Nim. I came across this thread by accident.
Thanks all for the clarifications. Yeah, I saw that igraph_small is just a convenience function.
I am just exploring a little bit igraph from Nim. I was just porting the examples.
With futhark it is quite straightforward the wrapping process. With just create.nim and running:
nim c create | |
---|---|
I get igraph_wrapper.nim. The difficult part is creating a Nim friendly API. But stimulus could be a great option. I will take a look. | |
I thought it was from iPod, iMac, iGraph! ;oP I'll fix it. Sorry |