How does Julia handle ccall when the return type has mutable structs vs when it has immutable structs?
Here's a simple library that has get_foos() function which returns a struct that has another struct with one member double.
typedef struct _Foo {
double a;
} Foo;
typedef struct _Foos {
Foo foo_a;
} Foos;
Foos get_foos() {
Foos foos;
foos.foo_a.a = 1 ;
return foos;
}
The following Julia code prints Foos(Foo(1.0)) as expected:
using Libdl
struct Foo
a::Cdouble
end
struct Foos
foo_a::Foo
end
function get_foos()
sdk_dll = Libdl.dlopen("libfos")
f = Libdl.dlsym(sdk_dll, :get_foos)
return ccall(f, Foos, ())
end
show(get_foos())
But if the inner struct is mutable, I get a segfault.
mutable struct Foo
a::Cdouble
end
struct Foos
foo_a::Foo
end
Julia 1.1, on Linux and OSX.
I'm assuming it's not a bug, but couldn't find enough information to figure out why that's happening.
Related
I am unsure about correct terms, but how do I use this:
type MyType map[string]string
as "data carrier" (or object in OOP)?
This does not work:
func NewMyType() *MyType {
return make(MyType)
}
I do want to use pointer but apparently this does not work, the compiler expects reference on return.
The builtin make() function creates a non-pointer value of your MyType map type, yet the return type is a pointer. That's what the error message tells if you try to compile it:
cannot use make(MyType) (type MyType) as type *MyType in return argument
If you return a pointer to the value, it works:
type MyType map[string]string
func NewMyType() *MyType {
m := make(MyType)
return &m
}
If you would want to use a single line for it, you could use a composite literal:
func NewMyType() *MyType {
return &MyType{}
}
But maps (map values) are already implement as pointers in the background, so this is redundant and unnecessary. Just return the map-value as-is:
type MyType map[string]string
func NewMyType() MyType {
return make(MyType)
}
Or with a composite literal:
func NewMyType() MyType {
return MyType{}
}
Although "constructors" for such simple types (simple creation) are not necessary, unless you want to do other things before returning it (e.g. specify its initial capacity or fill it with initial values).
For example
var myStructRef *Vertex
var myStruct Vertex
myStructRef = &Vertex{2, 3}
myStruct = Vertex{2, 3}
fmt.Println(myStructRef)
fmt.Println(myStruct)
changeByReferenceStruct(myStructRef)
changeByValueStruct(myStruct)
fmt.Println(myStructRef)
fmt.Println(myStruct)
And
func changeByValueStruct(myStruct Vertex) {
myStruct.X = 5
fmt.Println(myStruct)
}
func changeByReferenceStruct(myStruct *Vertex) {
myStruct.X = 7
fmt.Println(myStruct)
}
Isn't both myStructRef *Vertex and myStruct Vertex a pointer pointing to the struct itself? Why is there a discrepancy in behavior when I modify the struct in a function?
Is golang creating a new struct in changeByValueStruct when it resolves the parameter?
When you pass a pointer as an argument, what happens under the hood is that a copy of that pointer is created and passed to the underlying function. It should not be confused with pass-by-reference.
Let's look at an example to better grasp it:
package main
import (
"fmt"
)
type Point struct {
x int
y int
}
func (p Point) String() string {
return fmt.Sprintf("(%d, %d)", p.x, p.y)
}
func modifyValue(point Point) {
point.x += 10
}
func modifyPointer(point *Point) {
point.x = 5
point.y = 5
}
func modifyReference(point *Point) {
point = &Point{5, 5}
}
func main() {
p := Point{0, 0}
fmt.Println(p) // prints (0, 0)
modifyValue(p)
fmt.Println(p) // prints (0, 0)
modifyPointer(&p)
fmt.Println(p) // prints (5, 5)
p = Point{0, 0}
modifyReference(&p)
fmt.Println(p) // prints (0, 0)
}
What happens inside the modifyValue function is that a totally different instance of a Point structure is modified, so the value passed when calling the function is unaffected.
In the second example, a pointer to the structure is passed so the fields of the structure can be modified in a way that is visible from outside.
The most interesting point is made by the last function, modifyReference. If you are familiar with the pass by reference paradigm available in other languages you would expect to be able to modify the referenced object altogether, but this doesn't happen. It's because you're modifying a copy of the pointer passed as argument.
You may wonder, if everything is passed by value, when should you pass pointers and when values. Passing values assures the caller function that the passed structure cannot suffer any changes, so when you need this behaviour, go for the value. The downside of this is that a copy of the entire object is made and, if it is too big, memory becomes a concern.
If you're passing a big structure as an argument, using a pointer is better because it saves space, but you lose the guarantee that the object won't suffer any changes.
Passing struct to function argument makes copy of values. And passing pointer of struct doesn't. So passing struct can't update field value.
package main
import (
"fmt"
)
type Foo struct {
value int
}
func PassStruct(foo Foo) {
foo.value = 1
}
func PassStructPointer(foo *Foo) {
foo.value = 1
}
func main() {
var foo Foo
fmt.Printf("before PassStruct: %v\n", foo.value)
PassStruct(foo)
fmt.Printf("after PassStruct: %v\n", foo.value)
fmt.Printf("before PassStructPointer: %v\n", foo.value)
PassStructPointer(&foo)
fmt.Printf("after PassStructPointer: %v\n", foo.value)
}
https://play.golang.org/p/AM__JwyaJa
I'm having a lot of fun playing around with Rust having been a C# programmer for a long time but I have a question around reflection. Maybe I don't need reflection in this case but given that Rust is strongly typed I suspect I do (I would definitely need it in good ol' C#, bless its cotton socks).
I have this situation:
use std::collections::HashMap;
fn invoke_an_unknown_function(
hashmap: HashMap<String, String>,
// Something to denote a function I know nothing about goes here
) {
// For each key in the hash map, assign the value
// to the parameter argument whose name is the key
// and then invoke the function
}
How would I do that? I'm guessing I need to pass in some sort of MethodInfo as the second argument to the function and then poke around with that to get the arguments whose name is the key in the hash map and assign the values but I had a look around for the reflection API and found the following pre-Rust 1.0 documentation:
Module std::reflect
Module std::repr
[rust-dev] Reflection system
None of these give me enough to go on to get started. How would I implement the function I describe above?
Traits are the expected way to implement a fair amount of what reflection is (ab)used for elsewhere.
trait SomeInterface {
fn exposed1(&self, a: &str) -> bool;
fn exposed2(&self, b: i32) -> i32;
}
struct Implementation1 {
value: i32,
has_foo: bool,
}
impl SomeInterface for Implementation1 {
fn exposed1(&self, _a: &str) -> bool {
self.has_foo
}
fn exposed2(&self, b: i32) -> i32 {
self.value * b
}
}
fn test_interface(obj: &dyn SomeInterface) {
println!("{}", obj.exposed2(3));
}
fn main() {
let impl1 = Implementation1 {
value: 1,
has_foo: false,
};
test_interface(&impl1);
}
I have roughly the following code:
let val = util::replace(&mut self.some_field[i], self.some_method());
It fails with the following message:
unrelated.rs:61:65: 61:70 error: cannot borrow `*self` as immutable because it is also borrowed as mutable
unrelated.rs:61 let val = util::replace(&mut self.some_field[i], self.some_method());
^~~~~
unrelated.rs:61:36: 61:62 note: second borrow of `*self` occurs here
unrelated.rs:61 let val = util::replace(&mut self.some_field[i], self.some_method());
^~~~~~~~~~~~~~~~~~~~~~~
I can fix this by the following code:
let temp = self.some_method();
let val = util::replace(&mut self.some_field[i], temp);
But why does it fail? The scopes in which mutable and immutable pointers are taken are distinct, they are different expressions. It looks like kind of bug to me, but I just want to make sure that I'm not missing something here.
By introducing temp you've changed computation order: you first computed some_method(), then released self, and then got a mutable reference to some_field of self.
Rust does not allow holding mutable reference along with any other reference (mutable or immutable). See simpler example:
struct Foo {
a: int
}
impl Foo {
fn ff(&self) -> int { 1 }
}
fn fff(a: int, foo: &mut int) { }
fn ggg(foo: &mut int, a: int) { }
fn main() {
let mut foo = Foo { a: 0 };
fff(foo.ff(), &mut foo.a); // this call is valid
ggg(&mut foo.a, foo.ff()); // this is not
}
This is a bug: #6268.
It is because the borrow checker doesn't account for nested method calls properly yet: the nested calls should be equivalent to the code with the temporary (and thus, should be valid).
I'm confused as to why line 15 is not valid. Why can't a pointer to a big.Int be dereferenced, whilst a pointer to an int can?
package main
import (
"fmt"
"big"
)
func main() {
var c *int = getPtr()
fmt.Println(c)
fmt.Println(*c)
var d *big.Int = big.NewInt(int64(0))
fmt.Println(d)
// does not compile - implicit assignment of big.Int
// field 'neg' in function argument
//fmt.Println(*d)
}
func getPtr() *int {
var a int = 0
var b *int = &a
return b
}
It's because Int is a struct with unexported fields. When you pass a struct by value to a function, you're making a copy of it. The Go spec states that for this to be legal
...either all fields of T must be
exported, or the assignment must be in
the same package in which T is
declared. In other words, a struct
value can be assigned to a struct
variable only if every field of the
struct may be legally assigned
individually by the program.