diff options
author | Russ Cox <rsc@golang.org> | 2020-03-15 15:50:36 -0400 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2020-03-17 20:58:46 +0000 |
commit | 972d42d925e6cae3f8eebd9b21d445e06c2eb386 (patch) | |
tree | 737af27f0d49318b612efec874b1d1328c699d1a /content/c-go-cgo.article | |
parent | faf1e2da2d911edc717993e8edb24fe88f99b2b5 (diff) |
content: rename articles to reinforce convention of short URLs
The Go blog started out on Blogger
(http://web.archive.org/web/20100325005843/http://blog.golang.org/).
Later, we moved to the current self-hosted blog server
with extra Go-specific functionality like playground snippets.
The old Blogger posts have very long URLs that Blogger chose
for us, such as "go-programming-language-turns-two" or
"two-go-talks-lexical-scanning-in-go-and", predating
the convention of giving posts shorter, more share-friendly,
typeable names.
The conversion of the old Blogger posts also predated
the convention of putting supporting files in a subdirectory.
The result is that although we've established new conventions,
you wouldn't know by listing the directory - the old Blogger
content presents a conflicting picture.
This commit renames the posts with very long names
to have shorter, more share-friendly names, and it moves
all supporting files to subdirectories. It also adds a README
documenting the conventions.
For example, blog.golang.org/go-programming-language-turns-two
is now blog.golang.org/2years, matching our more recent birthday
post URLs, and its supporting files are moved to the new 2years/ directory.
The old URLs redirect to the new ones.
Change-Id: I9f46a790c2c8fab8459aeda73d4e3d2efc86d88f
Reviewed-on: https://go-review.googlesource.com/c/blog/+/223599
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Andrew Bonventre <andybons@golang.org>
Diffstat (limited to 'content/c-go-cgo.article')
-rw-r--r-- | content/c-go-cgo.article | 150 |
1 files changed, 0 insertions, 150 deletions
diff --git a/content/c-go-cgo.article b/content/c-go-cgo.article deleted file mode 100644 index b344def..0000000 --- a/content/c-go-cgo.article +++ /dev/null @@ -1,150 +0,0 @@ -# C? Go? Cgo! -17 Mar 2011 -Tags: cgo, technical -Summary: How to use cgo to let Go packages call C code. - -Andrew Gerrand - -## Introduction - -Cgo lets Go packages call C code. Given a Go source file written with some special features, -cgo outputs Go and C files that can be combined into a single Go package. - -To lead with an example, here's a Go package that provides two functions - -`Random` and `Seed` - that wrap C's `random` and `srandom` functions. - - package rand - - /* - #include <stdlib.h> - */ - import "C" - - func Random() int { - return int(C.random()) - } - - func Seed(i int) { - C.srandom(C.uint(i)) - } - -Let's look at what's happening here, starting with the import statement. - -The `rand` package imports `"C"`, but you'll find there's no such package -in the standard Go library. -That's because `C` is a "pseudo-package", -a special name interpreted by cgo as a reference to C's name space. - -The `rand` package contains four references to the `C` package: -the calls to `C.random` and `C.srandom`, the conversion `C.uint(i)`, -and the `import` statement. - -The `Random` function calls the standard C library's `random` function and returns the result. -In C, `random` returns a value of the C type `long`, -which cgo represents as the type `C.long`. -It must be converted to a Go type before it can be used by Go code outside this package, -using an ordinary Go type conversion: - - func Random() int { - return int(C.random()) - } - -Here's an equivalent function that uses a temporary variable to illustrate the type conversion more explicitly: - - func Random() int { - var r C.long = C.random() - return int(r) - } - -The `Seed` function does the reverse, in a way. -It takes a regular Go `int`, converts it to the C `unsigned int` type, -and passes it to the C function `srandom`. - - func Seed(i int) { - C.srandom(C.uint(i)) - } - -Note that cgo knows the `unsigned int` type as `C.uint`; -see the [cgo documentation](https://golang.org/cmd/cgo) for a complete -list of these numeric type names. - -The one detail of this example we haven't examined yet is the comment above the `import` statement. - - /* - #include <stdlib.h> - */ - import "C" - -Cgo recognizes this comment. Any lines starting with `#cgo` followed by -a space character are removed; -these become directives for cgo. -The remaining lines are used as a header when compiling the C parts of the package. -In this case those lines are just a single `#include` statement, -but they can be almost any C code. -The `#cgo` directives are used to provide flags for the compiler and linker -when building the C parts of the package. - -There is a limitation: if your program uses any `//export` directives, -then the C code in the comment may only include declarations (`extern int f();`), -not definitions (`int f() { return 1; }`). -You can use `//export` directives to make Go functions accessible to C code. - -The `#cgo` and `//export` directives are documented in the [cgo documentation](https://golang.org/cmd/cgo/). - -## Strings and things - -Unlike Go, C doesn't have an explicit string type. Strings in C are represented by a zero-terminated array of chars. - -Conversion between Go and C strings is done with the `C.CString`, -`C.GoString`, and `C.GoStringN` functions. -These conversions make a copy of the string data. - -This next example implements a `Print` function that writes a string to -standard output using C's `fputs` function from the `stdio` library: - - package print - - // #include <stdio.h> - // #include <stdlib.h> - import "C" - import "unsafe" - - func Print(s string) { - cs := C.CString(s) - C.fputs(cs, (*C.FILE)(C.stdout)) - C.free(unsafe.Pointer(cs)) - } - -Memory allocations made by C code are not known to Go's memory manager. -When you create a C string with `C.CString` (or any C memory allocation) -you must remember to free the memory when you're done with it by calling `C.free`. - -The call to `C.CString` returns a pointer to the start of the char array, -so before the function exits we convert it to an [`unsafe.Pointer`](https://golang.org/pkg/unsafe/#Pointer) -and release the memory allocation with `C.free`. -A common idiom in cgo programs is to [`defer`](https://golang.org/doc/articles/defer_panic_recover.html) -the free immediately after allocating (especially when the code that follows -is more complex than a single function call), -as in this rewrite of `Print`: - - func Print(s string) { - cs := C.CString(s) - defer C.free(unsafe.Pointer(cs)) - C.fputs(cs, (*C.FILE)(C.stdout)) - } - -## Building cgo packages - -To build cgo packages, just use [`go build`](https://golang.org/cmd/go/#Compile_packages_and_dependencies) -or [`go install`](https://golang.org/cmd/go/#Compile_and_install_packages_and_dependencies) as usual. -The go tool recognizes the special `"C"` import and automatically uses cgo for those files. - -## More cgo resources - -The [cgo command](https://golang.org/cmd/cgo/) documentation has more -detail about the C pseudo-package and the build process. -The [cgo examples](https://golang.org/misc/cgo/) in the Go tree demonstrate -more advanced concepts. - -Finally, if you're curious as to how all this works internally, -take a look at the introductory comment of the runtime package's [cgocall.go](https://golang.org/src/runtime/cgocall.go). |