As I understand it you can create an array(5) of int32 (int32 *) using newSeq[int32](5). This creates (besides other things) a memory area where 5 int32 are "layout" right after each other.
To hand this to a c-library you use addr(array[0]) because addr(array) is the location of a pointer (ref) which itself points to the nim internal seq representation, which is still not the start of the storage of the int32's.
I do it that way and it works, still I wonder if I miss something!
For reference a piece of code:
var ar = newSeq[int32](5)
echo "1: ", ar.repr
echo "2: ", addr(ar).repr
echo "3: ", addr(ar[0]).repr
echo "4: ", addr(ar[1]).repr
For example:
I wonder that this only works if array is a "var" but not if it is "let". I thought that newSeq[T]() always will allocate memory on the heap? Could we not get to the location where those int32 are in memory without using "var"?
I also wonder if I am right that arr.repr and addr(ar).repr show different values because in the first form the arr gets automatically dereferenced while in the second one gets the address of the memory location where the reference to the seq internal structure is stored.
To interface with a clib you may need to "keep" the data from being deleted by the GC when you leave the "scope" of "var". To prevent this you can add a GC_ref(ar) before handing it to a clib. You also need to store the "original" seq somewhere so you can GC_unref(ar) it later to let the GC free it eventually.
Now for the last question: Is there a (safe-)way which allows to get back from addr(ar[0]) to a ref one can GC_unref() if you know it is a "newSeqT"?
wonder that this only works if array is a "var" but not if it is "let".
Of course let makes not really sense with sequences. We use sequences when number of entries can change. For let we can not vary the number of elements, so we should use a plain array, or at least the compiler may use a plain array internally.
allows to get back from addr(ar[0]) to a ref
I guess the only way would be that the compiler scans all of its known sequences until its finds one pointing to that address.
Well ... I think not being able to take an address should not have something to do with mutability. So if the sequence is allocated in the heap it also should have an address.
let a1 = @[1,2,3]
echo a1[0]
echo a1[1]
echo a1[2]
echo addr(a1[2]).repr # no addr..
About finding the ref I wonder if there is something like "find the object which contains this memory address" if it is not possible to do some pointer juggling. To me it looks like the memory layout of a seq is continuous. In fact it looks like as if ar's memory location is always addr(ar[0])-16.
Well you already figured it out:
proc backToSeq[T](x: pointer): seq[T] =
cast[seq[T]](cast[int](x) - 2 * sizeof(int))
Could we not get to the location where those int32 are in memory without using "var"?
Of course, there is no technical difficulty here, it's just that the compiler is picky about your let variables. I like to introduce unsafeAddr or ffiAddr for this, I still don't like to allow let for addr even though addr is already unsafe.