diff options
Diffstat (limited to 'cshared/README.md')
-rw-r--r-- | cshared/README.md | 79 |
1 files changed, 0 insertions, 79 deletions
diff --git a/cshared/README.md b/cshared/README.md deleted file mode 100644 index ea32b4b..0000000 --- a/cshared/README.md +++ /dev/null @@ -1,79 +0,0 @@ -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.
\ No newline at end of file |