-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feature-request pointer size pair, (openArray as value) #5437
Comments
When proc foo(arg: openarray[int]; argLen0: int): void =
echo arg.low
echo arg.high
echo arg.len Currently it generates the following C code. N_NIMCALL(void, foo_OqSXkfoGaLLhgMRcwTdoHg)(NI* arg, NI argLen0, NI argLen0); |
A struct on its own makes C interop worse, not better, array,len pairs are common in C APIs, they usually don't have this wrapped as a struct. |
Yes it's true, in C a pointer, length pair is usually not wrapped in a struct. I think it is mostly for the reason, that such a struct would introduce more overhead to a C programming than it would solve. eg // version A
struct MyChildStructA* MotherGetAPtr(struct MyMotherStruct* arg) {
return &arg->childrenA;
}
struct MyChildStructB* MotherGetBPtr(struct MyMotherStruct* arg) {
return &arg->childrenB;
}
long MotherGetACount(struct MyMotherStruct* this) {
return arg->numA;
}
long MotherGetBCount(struct MyMotherStruct* this) {
return arg->numB;
}
// version B
void MotherGetChildrenA(struct MyMotherStruct* this, struct MyChildStructA** ptr, long* length) {
*ptr = &this->childrenA;
*length = &this->numA;
}
void MotherGetChildrenB(struct MyMotherStruct* this, struct MyChildStructB** ptr, long* length) {
*ptr = &this->childrenB;
*length = &this->numB;
} But in Nim pointers don't have pointer arithmetic (and that is a good thing), so this C API would not map into a good Nim API, unless a pointer/length pair is available. |
(This is a message to @krux02, since I don't think araq will be interested in a big change to the standard library.) I don't know about C interop, but for pure Nim a "SeqView" is invaluable. For example, what if you want to sort a sub-sequence? For memory-management, the View could hold a reference, but then maybe it's not as flexible as openarray. SeqView->ref seq, ArrayView[N]->ref Array, StringView->ref string. For that reason, I'm not sure of the best way to write such a library. |
@pb-cdunn I don't think I understand what you are saying, I rather think that my explanation for this feature request was not good enough to easily understand it. That is why I recently added the link the the c++ proposal, because it tries to explain the same thing just with different words.
The whole point of SeqView is to have something that is not as limiting as openarray. OpenArray is implemented, when you look at the generated C code, as a pointer and a size. The problem is, OpenArray is not available as a value type, and you can't set the pointer to point to some element of a seq, that is not the beginning, nor could you set the length to any value that is not the length of the seq you construct the openarray from. Maybe it is better to call the type from now on |
Reposting here from #7337 In the wild:
|
this has been implemented as |
@krux02 could we re-open this issue? I don't see how None of these /Users/timothee/git_clone//nim/Nim/lib/system.nim:4229: proc toOpenArray*[T](x: seq[T]; first, last: int): openarray[T] {. eg if the pointer comes from, say, a C function, how do I use toOpenArray ? Also, none of these
eg, span (https://stackoverflow.com/questions/45723819/what-is-a-span-and-when-should-i-use-one) allows for pointer + length. Likewise for D's arrays: int* ptr = c_func_returning_pointer();
int[] my_array = ptr[0..some_length];
// now we can pass around my_array and it works with all standard library etc |
I don't think we should reopen this issue. Most use cases are actually solved. But you are right. An unsafe toOpenArray from a pointer and a size has it's use cases and should be there. I think a new issue with a new name should be fine. |
Converting ptr+len to openarray: template ptrLenToOpenArray*[T](p: ptr T, s: int): auto =
toOpenArray(cast[ptr array[10000000, T]](p)[], 0, s - 1)
# test:
var a = @[1, 2, 3, 4]
var p = addr a[0]
proc foo(a: openarray[int]) =
echo @a
foo(ptrLenToOpenarray(p, 4)) |
@yglukhov don't use auto, use untyped. And isn't that |
@yglukhov sorry that's not a good workaround, the compiled time size is either too large or too small (too large will increase chance of stack overflow, too small will prevent that to work). As mentioned, most other languages have a clean way of doing that |
@timotheecour, sorry, but you could have checked the C codegen before writing your assumptions, but let me do this for you. Hint: compile time size is ignored. foo_I17oqmCE2MjmJ4Niaf1OnA((((NI*) (p_5oR9c2M9cr3Mo0CosBPfoglQ)))+(((NI) 0)), (((NI) 3))-(((NI) 0))+1); |
This idea is analogue to the c++ span type:
open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0122r1.pdf
The origin of this idea is, that I have written several C language wrappers and a repeating pattern to store a variable length array in a struct, is with the pointer/size pair. I use the following struct to solve the problem locally:
This is mostly for interfacing with C libraries. For example there is the C library that publishes the following api:
I would provide a wrapper like the following:
With proper Nim integration, this struct could provide iterators, index operators, conversion to
openArray
, so that it feels just like a Nim data structure.The reasone why a
seq
does not do the job, is because the seq has quite a different memory layout. The seq has two integers,len
andreserved
, then the data follows directly without another pointer indirection. This mains, that I can't fill theseq
header with just the right values, so that the seq sees the exact same data as the C library does (apart from that, I also don't know how well that would work together with garbage collection). And I also can't just copy the data. Copying the data would destroy the idea of the thin wrapper, and sometimes it is necessary to have write access the the members of theDataView
. Even though I am not entirely happy with the name, I still like theView
part of that name, because it implies, that one has only a view access to data. One is not responsible for freeing that memory, or able to keeping it alive over the owners lifetime. Other possible Names might beDataSlice
,DataWindow
or justopenArray
because it is semantically the same, just extended to be also be usable as values, not just function parameters.Further possibilities:
It could be used for slicing:
When
DataView
either becomes convertable toopenArray
, or becomesopenArray
, Then all algorithms that provide an interface to operate onopenArray
then automatically also become able to operate on any sub array of arrays and seqs.The text was updated successfully, but these errors were encountered: