Hi, a Nim newbie here, is there a way to set the data pointer of a Nim sequence? So that I could use the sequence to access memory that has been allocated by some library like PortAudio or OpenGL.
In Golang e.g. I would create a Golang slice and get access to its header, and set the "data" and "length" members of it, so that I can have runtime bounds checking for the external memory.
Thanks a lot!
seqs are exclusively managed by the Nim runtime, so even if you managed to create a seq with the base pointer to your external memory the runtime could try to free it etc.
UncheckedArrays are probably what you're looking for.
proc doSomethingWithPtr(x: pointer) =
let x = cast[ptr UncheckedArray[int]](x)
x[0] = 42
x[1] = 43
# if you want bound checking you want convert them to openArrays:
proc doWorkSafe(x: openArray[int]) =
assert x.len
echo x[0], x[1]
proc doSomethingUnsafe(x: pointer, len: int) =
doWorkSafe(toOpenArray(cast[ptr UncheckedArray[int]](x), 0, len-1))
I saw in some libraries and used the following technique to interop with C code. For example
// sum.c
long long sum(long long* xs, unsigned int len){
long long s = 0;
for(int i=0; i<len; i++) s += xs[i];
return s;
}
# sum.nim
{.compile: "sum.c" .}
proc sum(buf: ptr clonglong, len: csize_t): clonglong {.importc.}
proc sum_seq_wrapper(xs: seq[int]): int =
if xs.len == 0: return 0
let n = sum(cast[ptr clonglong](xs[0].unsafeAddr), xs.len.uint)
result = n.int
when isMainModule:
let xs = @[1,2,3]
echo sum_seq_wrapper(xs)
I am 100% sure, but it doesn't seem to me xs would be freed during sum. I also see people apply the same technique to string.