Reputation: 160
There is a simple example:
struct MyStruct
a: int
b: int
def my_proc(): unowned list of MyStruct
var result = new list of MyStruct
var my_struct = MyStruct()
for var i = 1 to 10
my_struct.a = i
my_struct.b = i*i
result.add(my_struct)
return result
init
pass
in case of compilation of this code, there is an error: "Local variable with strong reference used as return value and method return type has not been declared to transfer ownership". How to change a code that compilation took place successfully?
Upvotes: 1
Views: 394
Reputation: 4289
What made you think the return value should be unowned?
If it was because without unowned
the Vala compiler gave "error: 'MyStruct' is not a supported generic type argument, use '?' to box value types"
then you could try using list of MyStruct?
. This "boxes"[1][2] the basic C datatype so it can be used in the underlying GObject type system.
If it was because you read the tutorial and the sections on "Weak References", "Unowned References", "Ownership Transfer" and "Pointers" then I think you should view those topics as advanced topics. I'm thinking they should be moved at some point to a separate page for people who want to dig deep into Genie.
The Vala compiler, and so Genie, has assisted memory management. This means everything is taken care of for you in the background. The Vala compiler has sensible default behaviour and so you won't need to change things.
As a Genie programmer you should be aware of nullable types for interfacing with C libraries and that reference counting can create memory leaks when cyclical references are created[3]. Other than that look on the topics in that section of the Genie tutorial as for people who really want to dig deep into how Genie works and fix things.
Structs can be thought of as a forerunner of objects. Structs being a compound data type. The memory for structs in Vala/Genie are handled by the C compiler on the stack[4]. This potentially gives them a performance advantage. Generally, however, it is better to use a class for compound data types because they fit better with the underlying GObject type system. You may want to use structs, though, if you are trying to heavily optimize some code for speed[5] or interface with a C library that uses structs.
So the short answer is go with Jens' solution of using a class, unless you have a good reason not to.
[1] - https://docs.gtk.org/gobject/boxed.html
[2] - Vala interface generics compiler error
[3] - https://wiki.gnome.org/Projects/Vala/ReferenceHandling
[4] - https://wiki.gnome.org/Projects/Vala/Tutorial#Structs
[5] - http://zee-nix.blogspot.co.uk/2008/09/think-before-you-create-gobjects.html
Upvotes: 2
Reputation: 14873
A Genie list is really a Gee.List<T>
in "disguise" which is a class type, so it will be reference counted.
Also a type inferred var
variable is currently always an owned variable (there is a bug report about this in the Vala bug tracker).
So result
a strong reference to a class instance. You can't return that as an unowned reference.
I'd strongly advice you to use a class instead of a struct for MyStruct
.
Otherwise you will have memory management problems (structs are not reference counted).
You don't have to worry about copying and ownership then:
class MyStruct
a: int
b: int
def my_proc(): list of MyStruct
var result = new list of MyStruct
for var i = 1 to 10
var my_struct = new MyStruct()
my_struct.a = i
my_struct.b = i*i
result.add(my_struct)
return result
init
pass
Edit: If you want the list to contain multiple values, you have to allocate my_struct inside the loop as well! I have updated my code to reflect that.
Upvotes: 1
Reputation: 7153
There must be at least one reference to an object at any given time. Here, you create a variable result
which has a reference to a list. When you return it, the you insist that it is unowned list of MyStruct
. That means the return has no reference and result
goes out of scope, so the list now has no references to it and will be deallocated.
You are effectively returning a dangling reference. Either return list of MyStruct
, such that the caller has a reference or place a copy in some shared state (global variable or field).
Upvotes: 1