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
Binding to C flexible array members #10598
Comments
Does that mean, in C, that the array is inlined in the struct? |
The array is inlined in the struct. There is no extra pointer. Maybe you could take the struct pointer, offset to that member and cast types. It will be safe. |
This works: @[Link(ldflags: "#{__DIR__}/list.o")]
lib LibList
struct ListT
length : LibC::UInt
data : LibC::Int
end
fun new_list : ListT*
end
list_ptr = LibList.new_list
length = list_ptr.value.length
data = (list_ptr.as(LibC::UInt*) + 1).as(LibC::Int*)
p Slice.new(data, length) It's not ideal but it gets the job done. Alternatively I think |
This works as well @[Extern]
struct ListT
@length : LibC::UInt = 0
@data : LibC::Int = 0
def to_slice
Slice.new(pointerof(@data), @length)
end
end
@[Link(ldflags: "#{__DIR__}/list.o")]
lib LibList
fun new_list : ListT*
end
list_ptr = LibList.new_list
p list_ptr.value.to_slice |
It works! Also this: @[Link(ldflags: "#{__DIR__}/list.o")]
lib LibList
struct ListT
length : LibC::UInt
data : LibC::Int
end
fun new_list : ListT*
end
struct LibList::ListT
def to_slice
Slice.new(pointerof(@data), @length)
end
end
list_ptr = LibList.new_list
p list_ptr.value.to_slice |
Interesting, which should I use as a canonical solution? Frankly, now I wonder why declaring the member as a pointer itself doesn't work. |
Because it's not a pointer. The array is inlined in the struct. |
Maybe we could make it inline with an annotation. Let's leave this open. |
If we follow C's semantics, the VLA member will be ignored by lib LibList
struct ListT
length : LibC::UInt
data : LibC::Int[0]
end
end
struct LibList::ListT
def to_slice
Slice.new(@data.to_unsafe, @length)
end
end If there is an annotation for VLA members we could also check for constructs not allowed in C (e.g. VLAs not the end of a lib struct, VLA-containing structs as members of other structs), but that isn't necessary. |
Just ran into this for some |
Update: I seem to be having trouble with getting either @asterite's second solution or @HertzDevil's solution to work with more complex structs (specifically |
I was trying to work with a C library that has flexible array members declared in its structs and ran into trouble with using them in a
lib
declaration.Given a hypothetical
list.c
:Trying to treat it as a normal pointer causes a segfault:
Replacing the pointer with
LibC::Int[]
gives a parse failure.crystal --version
:The text was updated successfully, but these errors were encountered: