cshared

command
v3.1.0+incompatible Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 4, 2016 License: MIT Imports: 16 Imported by: 0

README

cshared

Building

go 1.6+

go build -o libgogit.so -buildmode=c-shared github.com/src-d/go-git/cshared

Two files must appear: libgogit.h and libgogit.so. The second must be a shared library, not an ar archive (may happen when something goes wrong). Check the exported symbols with nm -g.

How it works

Nearly every public Go function is mirrored in the corresponding *_cshared.go file. struct fields are also mirrored with getters and setters. The functions are marked with //export ... "magic" cgo comment so that they appear in defined symbols of a shared library built with -buildmode=c-shared.

Go pointers may not be passed out of cgo functions, so we maintain the two-way registry of all active Go objects mapped to Handle-s (uint64). Every time we need to return a reference to Go object outside, we call RegisterObject(interface{}) which returns a new Handle or reuses an existing one if the object has already been registered. Then we return the obtained Handle. When we need to receive a Go object reference in cgo function parameters, we accept uint64 and retrieve the interface{} with GetObject(Handle) which can be casted to the underlying type with a type assertion. When the object is no longer needed, we invoke UnregisterObject(Handle).

Although interface{] is just two uintptr-s inside, it is not a hashable type and we cannot use it a as key in our backward registry mapping. We are using the data uintptr as the key there. Since several distinct objects may exist with the same data pointer (e.g. struct and first field of the struct), the value of that mapping is a slice of Handle-s.

All the mentioned service functions are goroutine- and threadsafe.

std_cshared.go contains the cgo wrappers for standard library objects.

Debugging

c_dump_object() prints the current state of the two-way object registry to stdout. c_set_trace() activates echoing of RegisterObject() and UnregisterObject() invocations.

Caveats

Normally, we pass over a pointer to object as interface{} into RegisterObject() so that it can be mutated later. It requires the corresponding pointer-to-type type assertion in cgo functions. If you mess with this, the cgo function will, of course, panic.

A cgo function is allowed to take Go's string parameters. string's data must point to some memory and cgo does not copy the incoming foreign memory into Go memory automatically. What's worse, string-s are immutable and when you copy it, the copy points to the same memory. This means that if you pass in a string which was constructed using malloc(), for example, and later free() it, all Go strings created from the function parameter will point to the invalid memory. Actually, this allowance violates the cgo pointer passing rules stated just several blocks of texts below the example of string parameters - this is crazy, but we have to live with this, as usual in Go world. So, all incoming string-s must be immediately safely copied with CopyString() once they are used.

Returning strings and byte slices is also funny: you have to use C.CString -> *C.char and additionally return the length as another result tuple member if needed. C.CString copies the memory pointed by string to a malloc()-ed region and it is the responsibility of the other side to free() it or it will leak otherwise.

Another tricky part is in c_std_map_get_str_str and similar places where you need to return *C.char from an unaddressable array accessed under a pseudonym type through reflection. The only way I've found working is using reflect.Copy to byte slice (copy), then CBytes (copy) and finally another (copy) on the receiving side because the latter must be free()-d.

Documentation

Overview

+build ignore

+build ignore

+build ignore

+build ignore

+build ignore

+build ignore

+build ignore

+build ignore

+build ignore

+build ignore

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL