Kotlin Native Initialize Array of Struct - kotlin

In Kotlin/Native, what is the correct way to create and initialize an array of a structure? My code interfaces with a C library that defines the relevant structures as:
typedef struct VkDeviceQueueCreateInfo {
...
} VkDeviceQueueCreateInfo;
typedef struct VkDeviceCreateInfo {
...
uint32_t queueCreateInfoCount;
const VkDeviceQueueCreateInfo* pQueueCreateInfos;
...
} VkDeviceCreateInfo;
I've created wrapper classes DeviceQueueCreateInfo and DeviceCreateInfo. The Kotlin bindings are generated as classes inheriting from CStructVar and used like this:
class DeviceQueueCreateInfo(...) {
// Allocates in `scope` and fills a `VkDeviceQueueCreateInfo`
fun toRaw(scope: MemScope): VkDeviceQueueCreateInfo = ...
}
class DeviceCreateInfo(val queueCreateInfos: List<DeviceQueueCreateInfo>) {
// Allocates in `scope` and fills a `VkDeviceCreateInfo`
fun toRaw(scope: MemScope) = with(scope) {
alloc<VkDeviceCreateInfo>().also {
it.queueCreateInfoCount = queueCreateInfos.size.toUInt()
it.pQueueCreateInfos = ??? // Allocate array of struct in `scope`
}
}
}
I've added a ??? to the code to show where I'm having trouble. Kotlin NativePlacement has allocArray<T>(length: Int), so that was obviously my first stop:
it.pQueueCreateInfos = allocArray(queueCreateInfos.size)
And then to initialize them I tried:
it.pQueueCreateInfos = allocArray<VkDeviceQueueCreateInfo>(queueCreateInfos.size)
.also { arr ->
queueCreateInfos.forEachIndexed { index, x -> arr[index] = x.toRaw(scope) }
}
However, this fails to compile with error No set method providing array access at arr[index] = x. I wrote the following code which compiles and runs as expected:
val floats = listOf(1f, 2f, 3f)
allocArray<FloatVar>(floats.size).also { arr ->
floats.forEachIndexed { index, x -> arr[index] = x }
}
The code is identical apart from the type used, leading me to believe that I was perhaps trying to assign to an rvalue. I went looking for VkDeviceQueueCreateInfoVar only to find this:
Also, any C type has the Kotlin type representing the lvalue of this type, i.e., the value located in memory rather than a simple immutable self-contained value. Think C++ references, as a similar concept. For structs (and typedefs to structs) this representation is the main one and has the same name as the struct itself, for Kotlin enums it is named ${type}Var, for CPointer it is CPointerVar, and for most other types it is ${type}Var.
This states that for structs, the lvalue representation has the same name as the struct (no Var suffix)... so VkDeviceQueueCreateInfo should represent an assignable lvalue, and I'm confused as to why I am unable to assign values to my array. It occurs to me that Kotlin's assignment does something very different to a C assignment, but I had assumed there would be an idiomatic way to perform a structure assignment.
I've looked through the other overloads and methods in NativePlacement to find one that allows me to initialize the values in the newly created array, and I found allocArray<T>(length: Long, initializer: T.(index: Long)->Unit), but this seems to suffer from the same problem.
How do I allocate and initialize an array of structures through cinterop?

Related

Kotlin type inference for multiple possible types?

I have a function that takes parameter metadata of two possible types: Metadata1 or Metadata2. I'm trying to write a utility function that can be used for both since there is a ton of code reuse. Both of them have a list of DataPoint objects, each of which has name() method.
I thought in my code Kotlin would use type inference to know that dataPoints can only be one of two types that both have DataPoint.name() method, but I'm getting "unresolved reference: name". How can I make this function generic enough to apply to both Metadata1 and Metadata2?
var dataPoints: List<Any>
if (metadata is Metadata1) {
dataPoints = metadata.metadata1().dataPoints()
} else {
dataPoints = (metadata as Metadata2).metadata2().dataPoints()
}
if (data.size > 1) {
textView.test = dataPoints.fold("")
{ x, dataPoint ->
x + dataPoint.name() + " \n" // unresolved reference: name
}
}
This isn't unique to Kotlin, statically typed OOP languages work like this.
Your dataPoints is of type List<Any> and Any does not have a name() function. You're not showing a lot of code so I can't tell what kind of objects you have.
This is about run-time vs compile-time. The compiler can't predict what types you're going to put into your List<Any> at runtime and so the only functions you can call on its members are functions that belong to the Any class. Imagine if that list contained an object that didn't have a name() function. If the compiler allowed you to call name() then you'd have a run-time crash. This is why you get a compiler-time error when you try.
If you have two different types of objects that goes in the list, one way would be to make an interface that they both implement with shared methods in the interface. Which would look something like this:
interface Name {
fun name()
}
Change dataPoints to List<Name>, have your data classes implement that, and now dataPoint.name() compiles because the only objects allowed in the list are objects of type Name with a name() function.
var dataPoints: List<Name>
if (metadata is Metadata1) {
dataPoints = metadata.metadata1().dataPoints()
} else {
dataPoints = (metadata as Metadata2).metadata2().dataPoints()
}
if (data.size > 1) {
textView.test = dataPoints.fold("")
{ x, dataPoint ->
x + dataPoint.name() + " \n" // Compiles now
}
}
You have a similar problem with your Metadata1 and Metadata2 classes, they should probably implement an interface or extend a super class.

Indirect initialization of memory via UnsafeMutablePointer types

I encountered an unfamiliar pattern of initialization from Objective-C that I'm struggling to replicate in Swift.
Objective-C
In the example code, they defined a C struct such as this (abbreviated, original here):
struct AQPlayerState {
AudioFileID mAudioFile;
}
Here's an example that uses AQPlayerState:
AQPlayerState aqData; // 1
OSStattus result =
AudioFileOpenURL(
audioFileURL,
fsRdPerm,
0,
&aqData.mAudioFile // 2
);
The key takeaway from above is that aqData currently has uninitialized properties, and AudioFileOpenURL is initializing aqData.mAudioFile on it's behalf.
Swift
I'm trying to replicate this behaviour in Swift. Here's what I've tried so far:
Models:
class Person {
var name: String
init(name: String) {
self.name = name
}
}
class Foo {
var person: Person?
}
My idea was to replicate the Objective-C code by passing a reference of Foo.person into a function that would instantiate it on it's behalf.
Initialization Function:
func initializeWithBob(_ ptr: UnsafeMutablePointer<Person?>) {
ptr.pointee = Person(name: "Bob")
}
initializeWithBob takes a pointer to an address for a Person? type and initializes it with a Person(name: "Bob") object.
Here's my test code:
let foo = Foo()
let ptr = UnsafeMutablePointer<Person?>.allocate(capacity: 1)
ptr.initialize(to: foo.person)
defer {
ptr.deinitialize()
ptr.deallocate(capacity: 1)
}
initializeWithBob(ptr)
print(foo.person) // outputs nil
initializeWithBob failed to "install" an instance of type Person in my Foo instance. I presume some of my assumptions are wrong. Looking for help in correcting my assumptions and understanding of this situation.
Thanks in advance!
You can achieve what you are looking for via withUnsafeMutablePointer(to:_:) like so:
let foo = Foo()
withUnsafeMutablePointer(to: &foo.person) { (ptr) -> Void in
initializeWithBob(ptr)
}
print(foo.person!.name) // outputs Bob
However, I wouldn't recommend this approach. IMHO it makes more sense to wrap the APIs you are working with in a C function that you can make 'nice' to call from Swift. The problem with your current approach is that this type of Swift is hard to read for Swift developers and also hard to read for Audio Toolbox developers.
#kelvinlau Is this what you were thinking of trying to achieve?
func initializeWithBob(_ ptr: UnsafeMutablePointer<Foo>) {
ptr.pointee.person = Person(name: "Bob")
}
let foo = Foo()
let ptr = UnsafeMutablePointer<Foo>.allocate(capacity: 1)
ptr.initialize(to: foo)
initializeWithBob(ptr)
print(foo.person?.name ?? "nil")
ptr.deinitialize()
ptr.deallocate(capacity: 1)
print(foo.person?.name ?? "nil")
The code pattern you have in Objective-C is for out parameters, that is parameters which return a value, or in out parameters, that is parameters which both pass a value in and return one. Objective-C does not directly support these so pointers are used to produce the semantics.
Swift has in out parameters indicated by the keyword inout in the function declaration. Within the function an assignment to an inout parameters effectively assigns a value to the variable that was passed as the argument. At the function call site the variable must be prefixed by & to indicate it is the variable itself and not its value which is effectively being passed.
Keeping your Person and Foo as is your function becomes:
func initializeWithBob(_ ptr: inout Person?)
{
ptr = Person(name: "Bob")
}
and it may be used, for example, like:
var example = Foo()
initializeWithBob(&example.person)
Using inout in Swift is better than trying to build the same semantics using pointers.
HTH
Note: You can skip this unless you are curious
"Effectively" was used a few times above. Typically out parameters are implemented by the parameter passing method call-by-result, while in out use call-by-value-result. Using either of these methods the returned value is only assigned to the passed variable at the point the function returns.
Another parameter passing method is call-by-reference, which is similar to call-by-value-result except that each and every assignment to the parameter within the function is immediately made to passed variable. This means changes to the passed variable may be visible before the function returns.
Swift by design does not specify whether its inout uses call-by-value-result or call-by-reference. So rather than specify the exact semantics in the answer "effectively" is used.

Is Kotlin "pass-by-value" or "pass-by-reference"?

As I know Java is pass-by-value from this post. I am from Java background I wonder what Kotlin is using for passing values in between. Like in Extensions or Methods etc.
Every time I hear about the "pass-by-value" vs "pass-by-reference" Java debate I always think the same. The answer I give: "Java passes a copy (pass-by-value) of the reference (pass-by-reference)". So everyone is happy. I would say Kotlin does the same as it is JVM based language.
UPDATE
OK, so it's been a while since this answer and I think some clarification should be included. As #robert-liberatore is mentioning in the comments, the behaviour I'm describing is true for objects. Whenever your methods expect any object, you can assume that the JVM internally will make a copy of the reference to the object and pass it to your method. That's why having code like
void doSomething(List<Integer> x) {
x = new ArrayList<Integer>()
}
List<Integer> x = Arrays.asList(1, 2, 3);
doSomething(x);
x.length() == 3
behaves like it does. You're copying the reference to the list, so "reassigning it" will take no effect in the real object. But since you're referring to the same object, modifying its inner content will affect the outer object.
This is something you may miss when defining your attributes as final in order to achieve immutability. You won't be able to reassign them, but there's nothing preventing you from changing its content
Of course, this is true for objects where you have a reference. In case of primitives, which are not a reference to an object containing something but "something" themselves, the thing is different. Java will still make a copy of the whole value (as it does with the whole reference) and pass it to the method. But primitives are just values, you can't "modify its inner values". So any change inside a method will not have effect in the outer values
Now, talking about Kotlin
In Kotlin you "don't have" primitive values. But you "do have" primitive classes. Internally, the compiler will try to use JVM primitive values where needed but you can assume that you always work with the boxed version of the JVM primitives. Because of that, when possible the compiler will just make a copy of the primitive value and, in other scenarios, it will copy the reference to the object. Or with code
fun aJvmPrimitiveWillBeUsedHere(x: Int): Int = x * 2
fun aJvmObjectWillBeUsedHere(x: Int?): Int = if (x != null) x * 2 else 1
I'd say that Kotlin scenario is a bit safer than Java because it forces its arguments to be final. So you can modify its inner content but not reassign it
fun doSomething(x: MutableList<Int>) {
x.add(2) // this works, you can modify the inner state
x = mutableListOf(1, 2) // this doesn't work, you can't reassign an argument
}
It uses the same principles like Java. It is always pass-by-value, you can imagine that a copy is passed. For primitive types, e.g. Int this is obvious, the value of such an argument will be passed into a function and the outer variable will not be modified. Please note that parameters in Kotlin cannot be reassigned since they act like vals:
fun takeInt(a: Int) {
a = 5
}
This code will not compile because a cannot be reassigned.
For objects it's a bit more difficult but it's also call-by-value. If you call a function with an object, a copy of its reference is passed into that function:
data class SomeObj(var x: Int = 0)
fun takeObject(o: SomeObj) {
o.x = 1
}
fun main(args: Array<String>) {
val obj = SomeObj()
takeObject(obj)
println("obj after call: $obj") // SomeObj(x=1)
}
You can use a reference passed into a function to change the actual object.
The semantics is identical to Java.
In Java, when you have an instance of an object, and you pass it to a method, that method can change the state of that object, and when the method is done, the changes would have been applied to the object at the call site.
The same applies in Kotlin.
For primitives value is passed, and for non-primitives a reference to the object is passed. I'll explain with an example:
The code:
fun main() {
var a = 5
var b = a
a = 6
println("b = $b")
}
prints: b = 5
Kotlin passes the value of a to b, because a is a primitive. So changing a afterwards won't impact b.
The code:
fun main() {
var a = Dog(5)
var b = a
a.value = 6
println("b = ${b.value}")
}
class Dog (var value: Int)
prints b = 6, because this time a is not a primitive and so the reference to the object (Dog) was passed to b and not its value. Therefore changing a would affect all objects that point to it.
In Java primitive types like int, float, double, boolean are passed to a method by value, if you modify them inside the receiver method they doesn't change into the calling method. But if the property/variable type isn't a primitive, like arrays of primitives or other classes when they are changed inside the method that receive them as parameter they also change in the caller method.
But with Kotlin nothing seems to be primitive, so I think all is passed by reference.
This might be a little bit confusing.
The correct answer, IMHO, is that everything passes by reference, but no assignment is possible so it will be similar to passing by value in C++.
Note that function parameters are constant, i.e., they cannot be assigned.
Remember that in Kotlin there are no primitive types. Everything is an object.
When you write:
var x: Int = 3
x += 10
You actually create an object of type Int, assign it the value 3, and get a reference, or pointer, named x.
When you write
x += 10
You reassign a new Int object, with the value 13, to x. The older object becomes a garbage (and garbage-collected).
Of course, the compiler optimizes it, and creates no objects in the heap in this particular case, but conceptually it is as explained.
So what is the meaning of passing by reference function parameters?
Since no assignment is possible for function parameters, the main advantage of passing by reference in C++ does not exist in Kotlin.
If the object (passed to the function) has a method which changes its internal state, it will affect the original object.
No such method exists for Int, String, etc. They are immutable objects.
No copy is ever generated when passing objects to functions.
Bear in mind, am quite new to Kotlin. In my opinion, primitives are passed-by-value, but objects are passed-by-reference.
A primitive passed to a class works by default, but if you pass an object from a list, for example, and that object changes, the class object changes too. Because, in fact, it is the same object.
Additionally, if objects gets removed from the list, the class object IS STILL A REFERENCE. So it can still change due to references in other places.
Example below explaines. You can run it here.
fun main() {
val listObjects = mutableListOf(ClassB(), ClassB(), ClassB())
val listPrimitives = mutableListOf(111, 222, 333)
val test = ClassA()
test.ownedObject = listObjects[0]
test.ownedPrimitive = listPrimitives[0]
println("ownedObject: " + test.ownedObject.isEnabled +", ownedPrimitive: " +
test.ownedPrimitive)
listObjects[0].isEnabled = true
println("ownedObject: " + test.ownedObject.isEnabled +", ownedPrimitive: " +
test.ownedPrimitive)
listPrimitives[0] = 999
println("ownedObject: " + test.ownedObject.isEnabled +", ownedPrimitive: " +
test.ownedPrimitive)
}
class ClassA {
var ownedObject: ClassB = ClassB()
var ownedPrimitive: Int = 0
}
class ClassB {
var isEnabled = false
}
Since Kotlin is a new language for JVM, like Java it is pass-by-value. The confusing part is with object, at first it looks like that it is passed-by-reference but the actuality is that the reference/pointer itself is pass-by-value (a copy of a reference is passed to a method) hence when a method receives a reference to an object, the method can manipulate the original object.

Access method of extended type in Go

The follow codes produces "prog.go:17: c.Test undefined (type Child has no field or method Test)". (http://play.golang.org/p/g3InujEX9W)
package main
import "fmt"
type Base struct {
X int
}
func (b Base) Test() int {
return b.X
}
type Child Base
func main() {
c := Child{4}
fmt.Println(c.Test())
}
I realize Test is technically defined on Base, but should Child inherit that method?
the way to go for inheritance in go is using struct embedding with anonymous struct members.
Here is an adaption of your example.
Read about struct embedding and go's approach to inheritance etc here
The behaviour you encountered is expected and in sync with the golang specification, which explicitly states that:
The method set of any type T consists of all methods with receiver type T. The method set of the corresponding pointer type *T is the set of all methods with receiver *T or T (that is, it also contains the method set of T). Further rules apply to structs containing anonymous fields, as described in the section on struct types. Any other type has an empty method set.

Constructors in Go

I have a struct and I would like it to be initialised with some sensible default values.
Typically, the thing to do here is to use a constructor but since go isn't really OOP in the traditional sense these aren't true objects and it has no constructors.
I have noticed the init method but that is at the package level. Is there something else similar that can be used at the struct level?
If not what is the accepted best practice for this type of thing in Go?
There are some equivalents of constructors for when the zero values can't make sensible default values or for when some parameter is necessary for the struct initialization.
Supposing you have a struct like this :
type Thing struct {
Name string
Num int
}
then, if the zero values aren't fitting, you would typically construct an instance with a NewThing function returning a pointer :
func NewThing(someParameter string) *Thing {
p := new(Thing)
p.Name = someParameter
p.Num = 33 // <- a very sensible default value
return p
}
When your struct is simple enough, you can use this condensed construct :
func NewThing(someParameter string) *Thing {
return &Thing{someParameter, 33}
}
If you don't want to return a pointer, then a practice is to call the function makeThing instead of NewThing :
func makeThing(name string) Thing {
return Thing{name, 33}
}
Reference : Allocation with new in Effective Go.
There are actually two accepted best practices:
Make the zero value of your struct a sensible default. (While this looks strange to most people coming from "traditional" oop it often works and is really convenient).
Provide a function func New() YourTyp or if you have several such types in your package functions func NewYourType1() YourType1 and so on.
Document if a zero value of your type is usable or not (in which case it has to be set up by one of the New... functions. (For the "traditionalist" oops: Someone who does not read the documentation won't be able to use your types properly, even if he cannot create objects in undefined states.)
Go has objects. Objects can have constructors (although not automatic constructors). And finally, Go is an OOP language (data types have methods attached, but admittedly there are endless definitions of what OOP is.)
Nevertheless, the accepted best practice is to write zero or more constructors for your types.
As #dystroy posted his answer before I finished this answer, let me just add an alternative version of his example constructor, which I would probably write instead as:
func NewThing(someParameter string) *Thing {
return &Thing{someParameter, 33} // <- 33: a very sensible default value
}
The reason I want to show you this version is that pretty often "inline" literals can be used instead of a "constructor" call.
a := NewThing("foo")
b := &Thing{"foo", 33}
Now *a == *b.
There are no default constructors in Go, but you can declare methods for any type. You could make it a habit to declare a method called "Init". Not sure if how this relates to best practices, but it helps keep names short without loosing clarity.
package main
import "fmt"
type Thing struct {
Name string
Num int
}
func (t *Thing) Init(name string, num int) {
t.Name = name
t.Num = num
}
func main() {
t := new(Thing)
t.Init("Hello", 5)
fmt.Printf("%s: %d\n", t.Name, t.Num)
}
The result is:
Hello: 5
I like the explanation from this blog post:
The function New is a Go convention for packages that create a core type or different types for use by the application developer. Look at how New is defined and implemented in log.go, bufio.go and cypto.go:
log.go
// New creates a new Logger. The out variable sets the
// destination to which log data will be written.
// The prefix appears at the beginning of each generated log line.
// The flag argument defines the logging properties.
func New(out io.Writer, prefix string, flag int) * Logger {
return &Logger{out: out, prefix: prefix, flag: flag}
}
bufio.go
// NewReader returns a new Reader whose buffer has the default size.
func NewReader(rd io.Reader) * Reader {
return NewReaderSize(rd, defaultBufSize)
}
crypto.go
// New returns a new hash.Hash calculating the given hash function. New panics
// if the hash function is not linked into the binary.
func (h Hash) New() hash.Hash {
if h > 0 && h < maxHash {
f := hashes[h]
if f != nil {
return f()
}
}
panic("crypto: requested hash function is unavailable")
}
Since each package acts as a namespace, every package can have their own version of New. In bufio.go multiple types can be created, so there is no standalone New function. Here you will find functions like NewReader and NewWriter.
In Go, a constructor can be implemented using a function that returns a pointer to a modified structure.
type Colors struct {
R byte
G byte
B byte
}
// Constructor
func NewColors (r, g, b byte) *Colors {
return &Color{R:r, G:g, B:b}
}
For weak dependencies and better abstraction, the constructor does not return a pointer to a structure, but an interface that this structure implements.
type Painter interface {
paintMethod1() byte
paintMethod2(byte) byte
}
type Colors struct {
R byte
G byte
B byte
}
// Constructor return intreface
func NewColors(r, g, b byte) Painter {
return &Color{R: r, G: g, B: b}
}
func (c *Colors) paintMethod1() byte {
return c.R
}
func (c *Colors) paintMethod2(b byte) byte {
return c.B = b
}
another way is;
package person
type Person struct {
Name string
Old int
}
func New(name string, old int) *Person {
// set only specific field value with field key
return &Person{
Name: name,
}
}
If you want to force the factory function usage, name your struct (your class) with the first character in lowercase. Then, it won't be possible to instantiate directly the struct, the factory method will be required.
This visibility based on first character lower/upper case work also for struct field and for the function/method. If you don't want to allow external access, use lower case.
Golang is not OOP language in its official documents.
All fields of Golang struct has a determined value(not like c/c++), so constructor function is not so necessary as cpp.
If you need assign some fields some special values, use factory functions.
Golang's community suggest New.. pattern names.
I am new to go. I have a pattern taken from other languages, that have constructors. And will work in go.
Create an init method.
Make the init method an (object) once routine. It only runs the first time it is called (per object).
func (d *my_struct) Init (){
//once
if !d.is_inited {
d.is_inited = true
d.value1 = 7
d.value2 = 6
}
}
Call init at the top of every method of this class.
This pattern is also useful, when you need late initialisation (constructor is too early).
Advantages: it hides all the complexity in the class, clients don't need to do anything.
Disadvantages: you must remember to call Init at the top of every method of the class.