variable getter functions in golang - arrays

Consider the following stack implementation in go:
package main
import "fmt"
var a [10]int
var top int = -1
func main() {
printStack()
push(1)
printStack()
push(23)
printStack()
pop()
push(2)
printStack()
println("Top element is", getTop)
}
func push(x int) {
top += 1
a[top] = x
}
func pop() {
top -= 1
}
func getTop() int {
return a[top]
}
func printStack() {
fmt.Println(top+1, "Stack: ", a, "Top", getTop)
}
Questions:
When I use println("Top element is", getTop), it prints out memory address 0x193928 but when I call println("Top element is", getTop()), it returns 2. Returning 2 makes sense but I don't understand why its returning memory address? shouldn't call getTop without brackets be invalid?
It seems that you can't have variable & functions with same name in golang. is that correct assumption to make?
Play: https://play.golang.org/p/vvOGG296gr

You can pass your function as a var, for example: https://play.golang.org/p/wzGVtsEFQk . So getTop is a "function pointer", which explains the address being printed
Explained by #1: if it is declared in the same scope, your var name and function name collide

Related

Swift conversion of Array of Strings to C array of C Strings not working

The C function I wish to call is documented as:
GDALVectorTranslateOptions* GDALVectorTranslateOptionsNew(char** papszArgv, GDALVectorTranslateOptionsForBinary* psOptionsForBinary)
...and is imported to swift as:
public func GDALVectorTranslateOptionsNew(_ papszArgv: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>!, _ psOptionsForBinary: OpaquePointer!) -> OpaquePointer!
I have been unable to convert my swift array of strings into a C array of C strings in such a way that does not produce an error.
I have tried various methods found during research, and they all end up with similar errors being produced. My current method is to use the following function to convert the Swift array of strings to be used within a closure:
public func withArrayOfCStrings<R>(_ args: [String], _ body: ([UnsafeMutablePointer<CChar>?]) -> R) -> R {
var cStrings = args.map { strdup($0) }
cStrings.append(nil)
defer {
cStrings.forEach { free($0) }
}
return body(cStrings)
}
I'm attempting to use it all like this:
var opts = ["blah1", "blah2"]
withArrayOfCStrings(opts) { (cOpts) in
let translateOpts = GDALVectorTranslateOptionsNew(cOpts, nil)
}
But I get the error:
Cannot convert value of type '[UnsafeMutablePointer?]' (aka 'Array<Optional<UnsafeMutablePointer>>') to expected argument type 'UnsafeMutablePointer<UnsafeMutablePointer?>?'
How should I be doing this?
That withArrayOfCStrings function works with C functions taking a char * const * argument, i.e. a pointer to constant pointers to characters.
If you change the C declaration to
GDALVectorTranslateOptions* GDALVectorTranslateOptionsNew(char* const* papszArgv,
GDALVectorTranslateOptionsForBinary* psOptionsForBinary)
then it compiles and runs as expected.
If you do not have the option to modify the C code then you can change the helper method to
public func withArrayOfCStrings<R>(_ args: [String],
_ body: (UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>) -> R) -> R {
var cStrings = args.map { strdup($0) }
cStrings.append(nil)
defer {
cStrings.forEach { free($0) }
}
return body(&cStrings)
}
The body is now called with a UnsafeMutablePointer<UnsafeMutablePointer<Int8>?> argument, which corresponds to a C char ** argument.

String.withCString when the String is nil

The problem that'll be described relates to my previous question:
string.withCString and UnsafeMutablePointer(mutating: cstring) wrapped into a function which was my first approach to handle nil Strings (by putting withCString into a function)
and to a question which Mecki asked:
Why can't I pass an optional Swift String to C function that allows NULL pointers?
Imagine there is a c-function like:
unsigned long randomSign(char *pin, char *tag_signature, char *tag_data, char *xyz);
I know that the function works correctly if I wrap 4 string.withCString closures around the corresponding swift function:
// pin, tag_signature, tag_data and xyz are optional Strings so they may be nil which is a problem for my result.
// corresponding swift function:
// randomSign(pin: UnsafeMutablePointer<Int8>!, tag_signature: UnsafeMutablePointer<Int8>!, tag_data: UnsafeMutablePointer<Int8>!, xyz: UnsafeMutablePointer<Int8>!)
let result = pin.withCString { s1 in return
tag_signature.withCString {s2 in return
tag_data.withCString {s3 in return
xyz.withCString { s4 in return
randomSign(UnsafeMutablePointer(mutating: s1), UnsafeMutablePointer(mutating: s2), UnsafeMutablePointer(mutating: s3), UnsafeMutablePointer(mutating: s4))
}}}}
And so Martin R replied to an easier example, that it is not needed to wrap the closures around randomSign(arguments) and UnsafeMutablePointer(mutating: ...) because it can also take the strings and converts it.
But when I drop the closures and use it as Martin R described, it worked at the first launch on the simulator directly after starting the mac, but on consecutive calls of the randomSign-Function the return would tell me that for example the tag_signature or the pin would be invalid (but it actually is valid and I don't know why?!).
This leads me to the problem that I need the withCString closures (at the moment) but I have to handle nil-Strings, which would result the app to crash when it shall return the result because it couldn't evaluate the randomSign-Function.
So I tried to fit the approach below (also suggested by #Martin R) to Swift 3, but I did not workout to adapt it.
//Swift-2 written by Martin R
protocol CStringConvertible {
func withCString<Result>(#noescape f: UnsafePointer<Int8> throws -> Result) rethrows -> Result
}
extension String: CStringConvertible { }
extension Optional where Wrapped: CStringConvertible {
func withOptionalCString<Result>(#noescape f: UnsafePointer<Int8> -> Result) -> Result {
if let string = self {
return string.withCString(f)
} else {
return f(nil)
}
}
}
//Swift 3: ???
If anyone can tell me, why my function only works out when I use withCString but not when I dismiss it, I would be very grateful
and also if anyone knows how to solve the issue, i.e. correctly translating the swift-2 code to working swift-3 code.
The problem with
let result = randomSign(UnsafeMutablePointer(mutating: pin),
UnsafeMutablePointer(mutating: tag_signature),
UnsafeMutablePointer(mutating: tag_data),
UnsafeMutablePointer(mutating: xyz))
is that the temporary UTF-8 representation created from the Swift
strings is valid only during each call of UnsafeMutablePointer(),
but not necessarily still valid during the call of randomSign().
(So my final suggestion in https://stackoverflow.com/a/44027397/1187415
was actually not correct, I have updated that part).
A possible Swift 3 version of the wrapper in https://stackoverflow.com/a/39363769/1187415 is
extension Optional where Wrapped == String {
func withOptionalCString<Result>(_ f: (UnsafeMutablePointer<Int8>?) -> Result) -> Result {
if let string = self {
return string.withCString { f(UnsafeMutablePointer(mutating: $0)) }
} else {
return f(nil)
}
}
}
This handles both the optionality and casts the C string pointer
to a mutable pointer (as required by randomSign()). This can be
called as
let result = pin.withOptionalCString { s1 in
tag_signature.withOptionalCString { s2 in
tag_data.withOptionalCString { s3 in
xyz.withOptionalCString { s4 in
randomSign(s1, s2, s3, s4)
}
}
}
}
Remark: In theory, the problem can be avoided if the signature of randomSign() is changed to take const char * parameters:
unsigned long randomSign(const char *pin, const char *tag_signature, const char *tag_data, const char *xyz);
which one could then simply call as
let result = randomSign(pin, tag_signature, tag_data, xyz)
with optional or non-optional Swift strings.
However, this does currently not work, as reported in
SR-2814 Swift does not correctly pass in multiple optional strings to C function.

Pass Go function to C as callback

Suppose I have a C library with code like this:
typedef int (callback_t)(int);
void register_callback(callback_t cb);
I want to write go bindings for this function and pass arbitrary go callbacks.
I found an excellent answer here. However, it is a trick that makes use of the fact that the callback accepts a void *, through which Go passes the function pointer to C and receives it back. However, this can't be applied in my example since there isn't a user void *.
The best I could do is:
/*
extern int gobridge(int data);
static int cbridge(void)
{
register_callback(gobridge);
}
*/
import "C"
type Callback func (int) int
var g_cb Callback
//export gobridge
func gobridge(data C.int) C.int {
return C.int(g_cb(int(data)))
}
func RegisterCallback(cb Callback) {
g_cb = cb //save callback in a global
C.cbridge()
}
func Count(left, right int) {
C.count(C.int(left), C.int(right))
}
This only works for a single register_callback (because of the global variable), but the C library can register many callbacks and invoke them all.
I hoped to achieve something like this, but this doesn't compile (put aside the clojure, it can't convert the go function to c function even though the signature is the same):
import "C"
func RegisterCallback(cb Callback) {
f := func (d C.int) C.int {
return C.int(cb(int(d)))
}
C.register_callback(f)
}
func Count(left, right int) {
C.count(C.int(left), C.int(right))
}
Is there a way to properly bind the C library?
You could create an array of callbacks and have the bridge iterate the array of callbacks if the there is no return value (void function).

Why can't I populate and return my array created with rb_ary_new?

I'm not able to insert values into a Ruby array, and retrieve them later.
I put the results of different lines that I tried inside the first function. The results are:
VALUE rStraightCards;
static VALUE check_for_straight() {
stuff...
if (begin_straight != NOT_FOUND) {
for (i = begin_straight; i >= end_straight; i--) {
// this gives me a segmentation fault when I call straight_cards()
rb_ary_push(rStraightCards, i);
// these lines give me an empty ary when I call straight_cards()
// RARRAY_PTR(rStraightCards)[i] = i;
// RARRAY_PTR(rStraightCards)[INT2NUM(i)] = INT2NUM(i);
}
}
}
VALUE straight_cards() {
return rStraightCards;
}
void Init_straight_count() {
rStraightCards = rb_ary_new2(NUM_CARDS);
}
Both arguments for rb_ary_push are supposed to be of type VALUE but you're pushing an int (probably):
VALUE
rb_ary_push(VALUE ary, VALUE item)
{
rb_ary_modify(ary);
return rb_ary_push_1(ary, item);
}
Try this:
rb_ary_push(rStraightCards, INT2NUM(i));
I think it is worth noting that VALUE will usually be defined like this:
typedef uintptr_t VALUE;
So the usual warning flags for int-to-pointer conversions won't catch this sort of error.

Wrapping FUSE from Go

I'm playing around with wrapping FUSE with Go. However I've come stuck with how to deal with struct fuse_operations. I can't seem to expose the operations struct by declaring type Operations C.struct_fuse_operations as the members are lower case, and my pure-Go sources would have to use C-hackery to set the members anyway. My first error in this case is "can't set getattr" in what looks to be the Go equivalent of a default copy constructor. My next attempt is to expose an interface that expects GetAttr, ReadLink etc, and then generate C.struct_fuse_operations and bind the function pointers to closures that call the given interface.
This is what I've got (explanation continues after code):
package fuse
// #include <fuse.h>
// #include <stdlib.h>
import "C"
import (
//"fmt"
"os"
"unsafe"
)
type Operations interface {
GetAttr(string, *os.FileInfo) int
}
func Main(args []string, ops Operations) int {
argv := make([]*C.char, len(args) + 1)
for i, s := range args {
p := C.CString(s)
defer C.free(unsafe.Pointer(p))
argv[i] = p
}
cop := new(C.struct_fuse_operations)
cop.getattr = func(*C.char, *C.struct_stat) int {}
argc := C.int(len(args))
return int(C.fuse_main_real(argc, &argv[0], cop, C.size_t(unsafe.Sizeof(cop)), nil))
}
package main
import (
"fmt"
"fuse"
"os"
)
type CpfsOps struct {
a int
}
func (me *CpfsOps) GetAttr(string, *os.FileInfo) int {
return -1;
}
func main() {
fmt.Println(os.Args)
ops := &CpfsOps{}
fmt.Println("fuse main returned", fuse.Main(os.Args, ops))
}
This gives the following error:
fuse.go:21[fuse.cgo1.go:23]: cannot use func literal (type func(*_Ctype_char, *_Ctype_struct_stat) int) as type *[0]uint8 in assignment
I'm not sure what to pass to these members of C.struct_fuse_operations, and I've seen mention in a few places it's not possible to call from C back into Go code.
If it is possible, what should I do? How can I provide the "default" values for interface functions that acts as though the corresponding C.struct_fuse_operations member is set to NULL?
http://cheesesun.blogspot.com/2010/04/callbacks-in-cgo.html describes a general - if somewhat convoluted - technique. http://groups.google.com/group/golang-nuts/browse_thread/thread/abd0e30dafdbf297?tvc=2&pli=1 describes the problem.
I suspect that if you want to handle the function pointers as anything other than uintptrs, you'll have to hack on cgo.

Resources