Follow-up to Allow adding methods to C structs
Wrappers of C libraries are currently hindered because C/lib structs are not full-featured and have very strange and buggy behavior when it comes to constructors (see #557), so in order to make a proper interface for the library one has to make another type that represents this struct and convert to and from this type. Note, however, that these small structs are often abundantly used in libraries, and things like a huge array of structs is not rare. Copying and converting such an array N times per second is not good for performance, and neither are the ubiquitous conversions between the two types for function arguments and return values.
lib L
struct S
a : Int32
b : LibC::Char*
end
end
struct S
def initialize(@a : Int32, @b : LibC::Char*)
end
protected def initialize(s : L::S)
@a, @b = s.a, s.b
end
protected def to_c : L::S
L::S.new(a: @a, b: @b)
end
end
I would like to note that currently structs and lib structs behave mostly the same, and have the same field layout, as this example shows:
str = "abc"
arr = [S.new(5, str.to_unsafe), S.new(7, str.to_unsafe)]
larr = [] of L::S # needed because "can't execute `larr[1]` - Array(L::S) in `larr` was never instantiated"
larr = (pointerof(arr) as Pointer(Array(L::S))).value
p larr[1] #=> L::S(@a=7, @b=Pointer(UInt8)@0x435274)
Obviously, the example is vile, but my point is if the layout is the same then we should merge these two types into one thing.
The only problem is the ability to add fields anywhere in the code, which breaks everything.
So my suggestion is to make structs defined inside lib to be just like normal structs, but without the ability to add more fields to them. The syntax will also create the usual members in that struct, to not break backwards compatibility: initialize with 0 args that zeroes all fields, initialize with N args that sets all members, and property for each member. It is also important to be able to override all of these (maybe zeroing all bytes is not wanted, and maybe some special behavior for setters is wanted).
Sure, the inability to add fields still makes the structs "not full-featured" but how often does one really need to add fields to an existing type? This is a bad practice anyway.
The next step would be discussing what happens with inheritance. I think it should be possible to inherit from these structs and even add fields, as that doesn't affect interoperability. It would also be nice to have downcasting that drops the extra fields...
Follow-up to Allow adding methods to C structs
Wrappers of C libraries are currently hindered because C/lib structs are not full-featured and have very strange and buggy behavior when it comes to constructors (see #557), so in order to make a proper interface for the library one has to make another type that represents this struct and convert to and from this type. Note, however, that these small structs are often abundantly used in libraries, and things like a huge array of structs is not rare. Copying and converting such an array N times per second is not good for performance, and neither are the ubiquitous conversions between the two types for function arguments and return values.
I would like to note that currently structs and lib structs behave mostly the same, and have the same field layout, as this example shows:
Obviously, the example is vile, but my point is if the layout is the same then we should merge these two types into one thing.
The only problem is the ability to add fields anywhere in the code, which breaks everything.
So my suggestion is to make structs defined inside
libto be just like normal structs, but without the ability to add more fields to them. The syntax will also create the usual members in that struct, to not break backwards compatibility:initializewith 0 args that zeroes all fields,initializewith N args that sets all members, andpropertyfor each member. It is also important to be able to override all of these (maybe zeroing all bytes is not wanted, and maybe some special behavior for setters is wanted).Sure, the inability to add fields still makes the structs "not full-featured" but how often does one really need to add fields to an existing type? This is a bad practice anyway.
The next step would be discussing what happens with inheritance. I think it should be possible to inherit from these structs and even add fields, as that doesn't affect interoperability. It would also be nice to have downcasting that drops the extra fields...