blogng/blog/2015-03-29-notes-on-cgo.markdown
Dhananjay Balan 58b20109cf Convert from old categories to tags
import sys
import yaml

with open(sys.argv[1]) as fp:
    data = fp.read()

if not data.find("---") == 0:
    # no head
    print("NO YAML HEAD FOUND")
    sys.exit(-1)

data = data[3:]
head_end = data.find("---")

head = data[0:head_end]
data = data[head_end+3:]

metadata = yaml.safe_load(head)

cats = metadata.pop('categories', None)
if cats != None:
    if type(cats) == list:
        tags = cats
    elif type(cats) == str:
        tags = cats.split()

    tags = list(map(lambda t: t.lower(), tags))

    metadata["tags"] = ", ".join(tags)
    new_data = f"---\n{yaml.dump(metadata, default_flow_style=False)}---{data}"
    # write it
    print(f"coverted: categories to tags: {tags} - {sys.argv[1]}")
    with open(sys.argv[1], "w") as fp:
        fp.write(new_data)
    sys.exit(0)

if not metadata.get("tags", None):
    metadata["tags"] = "untagged"
    new_data = f"---\n{yaml.dump(metadata, default_flow_style=False)}---{data}"
    print(f"untagged: {sys.argv[1]}")
    # write it
    with open(sys.argv[1], "w") as fp:
        fp.write(new_data)
    sys.exit(0)

print("No changes needed")
2019-01-28 17:16:27 -05:00

129 lines
3.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
comments: true
date: 2015-03-29 00:28
layout: post
tags: golang, c
title: Notes on cgo
---
## Referencing c from go.
### Basic operation
import "C" imports the C namespace into go, the comment just above this statement is treated as C.
```c
/*
#include "add.h"
*/
import "C"
```
Everything you exported from c library is available in the C namespace.
```go
func main() {
fmt.Println(
C.add_two_numbers(3,4)
)
}
```
Building code is as easy as `go build`
Accessing standard types are easy as `C.char`, `C.int`. For complex types, prepend the type name with an underscore at end e.g `C.struct_stat`.
### Pointers and memory operations
Go provides an `unsafe` module. Gos GC cannot manage the memory allocated in C code, you should call `C.free(unsafe.Pointer)` (`free` is defined in `<stdlib.h>` ensure that this library is imported) to deallocate.
There are some special functions which convert Go types to C types and vice versa. (lifted from cgo documentation)
```go
// Go string to C string
// The C string is allocated in the C heap using malloc.
// It is the caller's responsibility to arrange for it to be
// freed, such as by calling C.free (be sure to include stdlib.h
// if C.free is needed).
func C.CString(string) *C.char
// C string to Go string
func C.GoString(*C.char) string
// C string, length to Go string
func C.GoStringN(*C.char, C.int) string
// C pointer, length to Go []byte
func C.GoBytes(unsafe.Pointer, C.int) []byte
```
### Accessing complex objects
Accessing structs from Go
```go
/*
struct person {
int age;
*/
// this can be used in go as
var p C.struct_person
p.age = 23
```
You can also pass pointers
```go
C.function_accepts_ptr_to_struct(&p)
```
Accessing Unions : No native counterpart, instead of converting it to a type, go treats them as a block of memory represented as byte array. Accessing data is done by casting unsafe.Pointer
```go
/*
union quant {
float weight;
int count;
};
*/
var q C.union_quant
ptr := (*float32)(unsafe.Pointer(&q))
*ptr = 3.14
```
## Extra goodies
### Compiler Flags
Compiler flags can be set using the `#cgo` directive. (`CFLAGS`, `LDFLAGS` etc)
```go
/*
#cgo: LDFLAGS: -lmath
#include <math.h>
*/
import "C"
```
### Restricting building
In many cases using cgo breaks the portability of your app, use build constraints to specify compatibility in source. Build constraints are comments which begin with
```go
// +build
```
Now, build comment must appear before package clause and should be followed by a blank line To restrict building just to Linux with cgo,
```go
// +build linux,cgo !darwin
package main
```
These are evaluated as `OR` of each constraint so the above line becomes `(linux AND cgo) OR (NOT darwin)`, also multiple build tags can be embedded in file.
There are other methods to restrict builds, see references.
## Reference
- [Link to example code gist](https://gist.github.com/dbalan/ace29f0c43638ee4f81d)
- [cgo Talk by Rajesh Ramachandran (Gophercon India)](https://www.youtube.com/watch?v=oeEVtyypYPg)
- [Conditional compilation with go build](http://dave.cheney.net/2013/10/12/how-to-use-conditional-compilation-with-the-go-build-tool)
- [cgo compiler directives](http://golang.org/cmd/cgo/)