mirror of
https://github.com/golang/go
synced 2024-11-21 21:04:41 -07:00
doc: add C? Go? Cgo! article
Originally published on The Go Programming Language Blog, March 17, 2011. http://blog.golang.org/2011/03/c-go-cgo.html Update #2547. R=golang-dev, adg CC=golang-dev https://golang.org/cl/5777054
This commit is contained in:
parent
c7cca2756e
commit
60b98d6208
159
doc/articles/c_go_cgo.html
Normal file
159
doc/articles/c_go_cgo.html
Normal file
@ -0,0 +1,159 @@
|
||||
<!--{
|
||||
"Title": "C? Go? Cgo!",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To lead with an example, here's a Go package that provides two functions -
|
||||
<code>Random</code> and <code>Seed</code> - that wrap C's <code>random</code>
|
||||
and <code>srandom</code> functions.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/cgo1.go" `/package rand/` `/END/`}}
|
||||
|
||||
<p>
|
||||
Let’s look at what's happening here, starting with the import statement.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The rand package imports "C", but you'll find there's no such package in
|
||||
the standard Go library. That's because <code>C</code> is a
|
||||
"pseudo-package", a special name interpreted by cgo as a reference to C's
|
||||
name space.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The rand package contains four references to the <code>C</code> package:
|
||||
the calls to <code>C.random</code> and <code>C.srandom</code>, the
|
||||
conversion <code>C.uint(i)</code>, and the import statement.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>Random</code> function calls the libc random function and returns
|
||||
the result. In C, random returns a value of the C type <code>long</code>,
|
||||
which cgo represents as the type <code>C.long</code>. 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:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/cgo1.go" `/func Random/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
Here’s an equivalent function that uses a temporary variable to illustrate
|
||||
the type conversion more explicitly:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/cgo2.go" `/func Random/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
The <code>Seed</code> function does the reverse, in a way. It takes a
|
||||
regular Go <code>int</code>, converts it to the C <code>unsigned int</code>
|
||||
type, and passes it to the C function srandom.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/cgo1.go" `/func Seed/` `/END/`}}
|
||||
|
||||
<p>
|
||||
Note that cgo knows the unsigned int type as C.uint; see the
|
||||
<a href="/cmd/cgo">cgo documentation</a> for a complete list of these
|
||||
numeric type names.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The one detail of this example we haven't examined yet is the comment
|
||||
above the import statement.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/cgo1.go" `/INCLUDE/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
Cgo recognizes this comment and uses it as a header when compiling the C
|
||||
parts of the package. In this case it is just a simple include statement,
|
||||
but it can be any valid C code. The comment must be immediately before the
|
||||
line that imports "C", without any intervening blank lines, just like a
|
||||
documentation comment.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Strings and things</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Unlike Go, C doesn’t have an explicit string type. Strings in C are
|
||||
represented by a zero-terminated array of chars.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Conversion between Go and C strings is done with the
|
||||
<code>C.CString</code>, <code>C.GoString</code>, and
|
||||
<code>C.GoStringN</code> functions. These conversions make a copy of the
|
||||
string data.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This next example implements a <code>Print</code> function that writes a
|
||||
string to standard output using C's <code>fputs</code> function from the
|
||||
<code>stdio</code> library:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/cgo3.go" `/package print/` `/END/`}}
|
||||
|
||||
<p>
|
||||
Memory allocations made by C code are not known to Go's memory manager.
|
||||
When you create a C string with <code>C.CString</code> (or any C memory
|
||||
allocation) you must remember to free the memory when you’re done with it
|
||||
by calling <code>C.free</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The call to <code>C.CString</code> returns a pointer to the start of the
|
||||
char array, so before the function exits we convert it to an
|
||||
<a href="/pkg/unsafe/#Pointer">unsafe.Pointer</a> and release the memory
|
||||
allocation with <code>C.free</code>. A common idiom in cgo programs is to
|
||||
<a href="/doc/articles/defer_panic_recover.html">defer</a> the free
|
||||
immediately after allocating (especially when the code that follows is more
|
||||
complex than a single function call), as in this rewrite of
|
||||
<code>Print</code>:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/cgo4.go" `/func Print/` `/END/`}}
|
||||
|
||||
<p>
|
||||
<b>Building cgo packages</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To build cgo packages, just use <a href="/cmd/go/#Compile_packages_and_dependencies">"go build"</a> or
|
||||
<a href="/cmd/go/#Compile_and_install_packages_and_dependencies">"go install"</a>
|
||||
as usual. The go tool recognizes the special "C" import and automatically uses
|
||||
cgo for those files.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>More cgo resources</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <a href="/cmd/cgo/">cgo command</a> documentation has more detail about
|
||||
the C pseudo-package and the build process. The cgo examples in the Go tree
|
||||
demonstrate more advanced concepts.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For a simple, idiomatic example of a cgo-based package, see Russ Cox’s <a
|
||||
href="http://code.google.com/p/gosqlite/source/browse/sqlite/sqlite.go">gosqlite</a>.
|
||||
Also, the Go Project Dashboard lists <a
|
||||
href="https://godashboard.appspot.com/project?tag=cgo">several other
|
||||
cgo packages</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Finally, if you’re curious as to how all this works internally, take a look
|
||||
at the introductory comment of the runtime package’s <a href="/src/pkg/runtime/cgocall.c">cgocall.c</a>.
|
||||
</p>
|
@ -126,7 +126,7 @@ Guided tours of Go programs.
|
||||
|
||||
<ul>
|
||||
<li><a href="/doc/articles/go_command.html">About the Go command</a> - why we wrote it, what it is, what it's not, and how to use it.</li>
|
||||
<li><a href="http://blog.golang.org/2011/03/c-go-cgo.html">C? Go? Cgo!</a> - linking against C code with <a href="/cmd/cgo/">cgo</a>.</li>
|
||||
<li><a href="/doc/articles/c_go_cgo.html">C? Go? Cgo!</a> - linking against C code with <a href="/cmd/cgo/">cgo</a>.</li>
|
||||
<li><a href="http://blog.golang.org/2011/03/godoc-documenting-go-code.html">Godoc: documenting Go code</a> - writing good documentation for <a href="/cmd/godoc/">godoc</a>.</li>
|
||||
<li><a href="http://blog.golang.org/2011/06/profiling-go-programs.html">Profiling Go Programs</a></li>
|
||||
</ul>
|
||||
|
23
doc/progs/cgo1.go
Normal file
23
doc/progs/cgo1.go
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
package rand
|
||||
|
||||
// INCLUDE OMIT
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// STOP OMIT
|
||||
func Random() int {
|
||||
return int(C.random())
|
||||
}
|
||||
|
||||
// STOP OMIT
|
||||
func Seed(i int) {
|
||||
C.srandom(C.uint(i))
|
||||
}
|
||||
|
||||
// END OMIT
|
21
doc/progs/cgo2.go
Normal file
21
doc/progs/cgo2.go
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
package rand2
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func Random() int {
|
||||
var r C.long = C.random()
|
||||
return int(r)
|
||||
}
|
||||
|
||||
// STOP OMIT
|
||||
func Seed(i int) {
|
||||
C.srandom(C.uint(i))
|
||||
}
|
||||
|
||||
// END OMIT
|
17
doc/progs/cgo3.go
Normal file
17
doc/progs/cgo3.go
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
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))
|
||||
}
|
||||
|
||||
// END OMIT
|
17
doc/progs/cgo4.go
Normal file
17
doc/progs/cgo4.go
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
package print
|
||||
|
||||
// #include <stdio.h>
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func Print(s string) {
|
||||
cs := C.CString(s)
|
||||
defer C.free(unsafe.Pointer(cs))
|
||||
C.fputs(cs, (*C.FILE)(C.stdout))
|
||||
}
|
||||
|
||||
// END OMIT
|
@ -28,7 +28,14 @@ law_of_reflection="
|
||||
interface2
|
||||
"
|
||||
|
||||
all=$(echo $defer_panic_recover $effective_go $error_handling $law_of_reflection slices go1)
|
||||
c_go_cgo="
|
||||
cgo1
|
||||
cgo2
|
||||
cgo3
|
||||
cgo4
|
||||
"
|
||||
|
||||
all=$(echo $defer_panic_recover $effective_go $error_handling $law_of_reflection $c_go_cgo slices go1)
|
||||
|
||||
for i in $all; do
|
||||
go build $i.go
|
||||
|
@ -1,6 +1,6 @@
|
||||
<!--{
|
||||
"Title": "References",
|
||||
"Path": "/ref/"
|
||||
"Path": "/ref/"
|
||||
}-->
|
||||
|
||||
<img class="gopher" src="/doc/gopher/ref.png" />
|
||||
@ -61,7 +61,7 @@ Using GDB to debug Go programs.
|
||||
<h3 id="articles">Articles</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="http://blog.golang.org/2011/03/c-go-cgo.html">C? Go? Cgo!</a> - linking against C code with <a href="/cmd/cgo/">cgo</a>.</li>
|
||||
<li><a href="/doc/articles/c_go_cgo.html">C? Go? Cgo!</a> - linking against C code with <a href="/cmd/cgo/">cgo</a>.</li>
|
||||
<li><a href="/doc/articles/defer_panic_recover.html">Defer, Panic, and Recover</a></li>
|
||||
<li><a href="/doc/articles/slices_usage_and_internals.html">Go Slices: usage and internals</a></li>
|
||||
<li><a href="http://blog.golang.org/2011/03/godoc-documenting-go-code.html">Godoc: documenting Go code</a> - writing good documentation for <a href="/cmd/godoc/">godoc</a>.</li>
|
||||
|
@ -123,6 +123,6 @@ and $GOROOT/misc/cgo/gmp for examples.
|
||||
Cgo does not yet work with gccgo.
|
||||
|
||||
See "C? Go? Cgo!" for an introduction to using cgo:
|
||||
http://blog.golang.org/2011/03/c-go-cgo.html
|
||||
http://golang.org/doc/articles/c_go_cgo.html
|
||||
*/
|
||||
package documentation
|
||||
|
Loading…
Reference in New Issue
Block a user