libgo: add misc/cgo files
Copy all the misc/cgo files from the gc toolchain into libgo/misc. These will be used for testing purposes by later changes to the gotools directory. Reviewed-on: https://go-review.googlesource.com/46721 From-SVN: r249674
This commit is contained in:
parent
9913ef5866
commit
936615752a
|
@ -1,4 +1,4 @@
|
|||
bfb18fb16194826bf2bf2d7af873719ddb5e8e42
|
||||
040dc31406d580e33f82e578a840600fea5004ef
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
|
|
@ -182,6 +182,13 @@ done
|
|||
done
|
||||
done
|
||||
|
||||
(cd ${NEWDIR}/misc/cgo && find . -type f -print) | while read f; do
|
||||
oldfile=${OLDDIR}/misc/cgo/$f
|
||||
newfile=${NEWDIR}/misc/cgo/$f
|
||||
libgofile=misc/cgo/$f
|
||||
merge $f ${oldfile} ${newfile} ${libgofile}
|
||||
done
|
||||
|
||||
(cd ${OLDDIR}/src && find . -name '*.go' -print) | while read f; do
|
||||
oldfile=${OLDDIR}/src/$f
|
||||
newfile=${NEWDIR}/src/$f
|
||||
|
@ -197,5 +204,20 @@ done
|
|||
git rm ${libgofile}
|
||||
done
|
||||
|
||||
(cd ${OLDDIR}/misc/cgo && find . -type f -print) | while read f; do
|
||||
oldfile=${OLDDIR}/misc/cgo/$f
|
||||
newfile=${NEWDIR}/misc/cgo/$f
|
||||
libgofile=misc/cgo/$f
|
||||
if test -f ${newfile}; then
|
||||
continue
|
||||
fi
|
||||
if ! test -f ${libgofile}; then
|
||||
continue
|
||||
fi
|
||||
echo "merge.sh: ${libgofile}: REMOVED"
|
||||
rm -f ${libgofile}
|
||||
git rm ${libgofile}
|
||||
done
|
||||
|
||||
(echo ${new_rev}; sed -ne '2,$p' MERGE) > MERGE.tmp
|
||||
mv MERGE.tmp MERGE
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2013 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 main
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -c
|
||||
|
||||
void test() {
|
||||
xxx; // ERROR HERE
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func main() {
|
||||
C.test()
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2013 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 main
|
||||
|
||||
import "C"
|
||||
|
||||
func main() {
|
||||
s := ""
|
||||
_ = s
|
||||
C.malloc(s) // ERROR HERE
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2014 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 main
|
||||
|
||||
/*
|
||||
typedef struct foo foo_t;
|
||||
typedef struct bar bar_t;
|
||||
|
||||
foo_t *foop;
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func main() {
|
||||
x := (*C.bar_t)(nil)
|
||||
C.foop = x // ERROR HERE
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2015 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 main
|
||||
|
||||
/*
|
||||
//enum test { foo, bar };
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func main() {
|
||||
var a = C.enum_test(1) // ERROR HERE
|
||||
_ = a
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2015 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 main
|
||||
|
||||
/*
|
||||
//enum test { foo, bar };
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func main() {
|
||||
p := new(C.enum_test) // ERROR HERE
|
||||
_ = p
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright 2015 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.
|
||||
|
||||
// issue 13129: used to output error about C.unsignedshort with CC=clang
|
||||
|
||||
package main
|
||||
|
||||
import "C"
|
||||
|
||||
func main() {
|
||||
var x C.ushort
|
||||
x = int(0) // ERROR HERE
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright 2015 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 main
|
||||
|
||||
// #include <stdio.h>
|
||||
import "C"
|
||||
|
||||
func main() {
|
||||
_ = C.fopen() // ERROR HERE
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2015 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.
|
||||
|
||||
// issue 13635: used to output error about C.unsignedchar.
|
||||
// This test tests all such types.
|
||||
|
||||
package pkg
|
||||
|
||||
import "C"
|
||||
|
||||
func main() {
|
||||
var (
|
||||
_ C.uchar = "uc" // ERROR HERE
|
||||
_ C.schar = "sc" // ERROR HERE
|
||||
_ C.ushort = "us" // ERROR HERE
|
||||
_ C.uint = "ui" // ERROR HERE
|
||||
_ C.ulong = "ul" // ERROR HERE
|
||||
_ C.longlong = "ll" // ERROR HERE
|
||||
_ C.ulonglong = "ull" // ERROR HERE
|
||||
_ C.complexfloat = "cf" // ERROR HERE
|
||||
_ C.complexdouble = "cd" // ERROR HERE
|
||||
)
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2016 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.
|
||||
|
||||
// cgo converts C void* to Go unsafe.Pointer, so despite appearances C
|
||||
// void** is Go *unsafe.Pointer. This test verifies that we detect the
|
||||
// problem at build time.
|
||||
|
||||
package main
|
||||
|
||||
// typedef void v;
|
||||
// void F(v** p) {}
|
||||
import "C"
|
||||
|
||||
import "unsafe"
|
||||
|
||||
type v [0]byte
|
||||
|
||||
func f(p **v) {
|
||||
C.F((**C.v)(unsafe.Pointer(p))) // ERROR HERE
|
||||
}
|
||||
|
||||
func main() {
|
||||
var p *v
|
||||
f(&p)
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2016 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.
|
||||
|
||||
// Issue 14669: test that fails when build with CGO_CFLAGS selecting
|
||||
// optimization.
|
||||
|
||||
package p
|
||||
|
||||
/*
|
||||
const int E = 1;
|
||||
|
||||
typedef struct s {
|
||||
int c;
|
||||
} s;
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func F() {
|
||||
_ = C.s{
|
||||
c: C.E,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright 2016 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 main
|
||||
|
||||
// void f(void *p, int x) {}
|
||||
import "C"
|
||||
|
||||
func main() {
|
||||
_ = C.f(1) // ERROR HERE
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2016 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.
|
||||
|
||||
// Issue 16591: Test that we detect an invalid call that was being
|
||||
// hidden by a type conversion inserted by cgo checking.
|
||||
|
||||
package p
|
||||
|
||||
// void f(int** p) { }
|
||||
import "C"
|
||||
|
||||
type x *C.int
|
||||
|
||||
func F(p *x) {
|
||||
C.f(p) // ERROR HERE
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright 2014 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 main
|
||||
|
||||
/*
|
||||
void foo() {}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func main() {
|
||||
C.foo = C.foo // ERROR HERE
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2014 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 main
|
||||
|
||||
// Issue 8442. Cgo output unhelpful error messages for
|
||||
// invalid C preambles.
|
||||
|
||||
/*
|
||||
void issue8442foo(UNDEF*); // ERROR HERE
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func main() {
|
||||
C.issue8442foo(nil)
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2016 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.
|
||||
|
||||
// Test that C.malloc does not return nil.
|
||||
|
||||
package main
|
||||
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var size C.size_t
|
||||
size--
|
||||
|
||||
// The Dragonfly libc succeeds when asked to allocate
|
||||
// 0xffffffffffffffff bytes, so pass a different value that
|
||||
// causes it to fail.
|
||||
if runtime.GOOS == "dragonfly" {
|
||||
size = C.size_t(0x7fffffff << (32 * (^uintptr(0) >> 63)))
|
||||
}
|
||||
|
||||
p := C.malloc(size)
|
||||
if p == nil {
|
||||
fmt.Println("malloc: C.malloc returned nil")
|
||||
// Just exit normally--the test script expects this
|
||||
// program to crash, so exiting normally indicates failure.
|
||||
}
|
||||
}
|
|
@ -0,0 +1,576 @@
|
|||
// Copyright 2015 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.
|
||||
|
||||
// Tests that cgo detects invalid pointer passing at runtime.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// ptrTest is the tests without the boilerplate.
|
||||
type ptrTest struct {
|
||||
name string // for reporting
|
||||
c string // the cgo comment
|
||||
imports []string // a list of imports
|
||||
support string // supporting functions
|
||||
body string // the body of the main function
|
||||
extra []extra // extra files
|
||||
fail bool // whether the test should fail
|
||||
expensive bool // whether the test requires the expensive check
|
||||
}
|
||||
|
||||
type extra struct {
|
||||
name string
|
||||
contents string
|
||||
}
|
||||
|
||||
var ptrTests = []ptrTest{
|
||||
{
|
||||
// Passing a pointer to a struct that contains a Go pointer.
|
||||
name: "ptr1",
|
||||
c: `typedef struct s { int *p; } s; void f(s *ps) {}`,
|
||||
body: `C.f(&C.s{new(C.int)})`,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
// Passing a pointer to a struct that contains a Go pointer.
|
||||
name: "ptr2",
|
||||
c: `typedef struct s { int *p; } s; void f(s *ps) {}`,
|
||||
body: `p := &C.s{new(C.int)}; C.f(p)`,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
// Passing a pointer to an int field of a Go struct
|
||||
// that (irrelevantly) contains a Go pointer.
|
||||
name: "ok1",
|
||||
c: `struct s { int i; int *p; }; void f(int *p) {}`,
|
||||
body: `p := &C.struct_s{i: 0, p: new(C.int)}; C.f(&p.i)`,
|
||||
fail: false,
|
||||
},
|
||||
{
|
||||
// Passing a pointer to a pointer field of a Go struct.
|
||||
name: "ptr-field",
|
||||
c: `struct s { int i; int *p; }; void f(int **p) {}`,
|
||||
body: `p := &C.struct_s{i: 0, p: new(C.int)}; C.f(&p.p)`,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
// Passing a pointer to a pointer field of a Go
|
||||
// struct, where the field does not contain a Go
|
||||
// pointer, but another field (irrelevantly) does.
|
||||
name: "ptr-field-ok",
|
||||
c: `struct s { int *p1; int *p2; }; void f(int **p) {}`,
|
||||
body: `p := &C.struct_s{p1: nil, p2: new(C.int)}; C.f(&p.p1)`,
|
||||
fail: false,
|
||||
},
|
||||
{
|
||||
// Passing the address of a slice with no Go pointers.
|
||||
name: "slice-ok-1",
|
||||
c: `void f(void **p) {}`,
|
||||
imports: []string{"unsafe"},
|
||||
body: `s := []unsafe.Pointer{nil}; C.f(&s[0])`,
|
||||
fail: false,
|
||||
},
|
||||
{
|
||||
// Passing the address of a slice with a Go pointer.
|
||||
name: "slice-ptr-1",
|
||||
c: `void f(void **p) {}`,
|
||||
imports: []string{"unsafe"},
|
||||
body: `i := 0; s := []unsafe.Pointer{unsafe.Pointer(&i)}; C.f(&s[0])`,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
// Passing the address of a slice with a Go pointer,
|
||||
// where we are passing the address of an element that
|
||||
// is not a Go pointer.
|
||||
name: "slice-ptr-2",
|
||||
c: `void f(void **p) {}`,
|
||||
imports: []string{"unsafe"},
|
||||
body: `i := 0; s := []unsafe.Pointer{nil, unsafe.Pointer(&i)}; C.f(&s[0])`,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
// Passing the address of a slice that is an element
|
||||
// in a struct only looks at the slice.
|
||||
name: "slice-ok-2",
|
||||
c: `void f(void **p) {}`,
|
||||
imports: []string{"unsafe"},
|
||||
support: `type S struct { p *int; s []unsafe.Pointer }`,
|
||||
body: `i := 0; p := &S{p:&i, s:[]unsafe.Pointer{nil}}; C.f(&p.s[0])`,
|
||||
fail: false,
|
||||
},
|
||||
{
|
||||
// Passing the address of a slice of an array that is
|
||||
// an element in a struct, with a type conversion.
|
||||
name: "slice-ok-3",
|
||||
c: `void f(void* p) {}`,
|
||||
imports: []string{"unsafe"},
|
||||
support: `type S struct { p *int; a [4]byte }`,
|
||||
body: `i := 0; p := &S{p:&i}; s := p.a[:]; C.f(unsafe.Pointer(&s[0]))`,
|
||||
fail: false,
|
||||
},
|
||||
{
|
||||
// Passing the address of a slice of an array that is
|
||||
// an element in a struct, with a type conversion.
|
||||
name: "slice-ok-4",
|
||||
c: `typedef void* PV; void f(PV p) {}`,
|
||||
imports: []string{"unsafe"},
|
||||
support: `type S struct { p *int; a [4]byte }`,
|
||||
body: `i := 0; p := &S{p:&i}; C.f(C.PV(unsafe.Pointer(&p.a[0])))`,
|
||||
fail: false,
|
||||
},
|
||||
{
|
||||
// Passing the address of a static variable with no
|
||||
// pointers doesn't matter.
|
||||
name: "varok",
|
||||
c: `void f(char** parg) {}`,
|
||||
support: `var hello = [...]C.char{'h', 'e', 'l', 'l', 'o'}`,
|
||||
body: `parg := [1]*C.char{&hello[0]}; C.f(&parg[0])`,
|
||||
fail: false,
|
||||
},
|
||||
{
|
||||
// Passing the address of a static variable with
|
||||
// pointers does matter.
|
||||
name: "var",
|
||||
c: `void f(char*** parg) {}`,
|
||||
support: `var hello = [...]*C.char{new(C.char)}`,
|
||||
body: `parg := [1]**C.char{&hello[0]}; C.f(&parg[0])`,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
// Storing a Go pointer into C memory should fail.
|
||||
name: "barrier",
|
||||
c: `#include <stdlib.h>
|
||||
char **f1() { return malloc(sizeof(char*)); }
|
||||
void f2(char **p) {}`,
|
||||
body: `p := C.f1(); *p = new(C.char); C.f2(p)`,
|
||||
fail: true,
|
||||
expensive: true,
|
||||
},
|
||||
{
|
||||
// Storing a Go pointer into C memory by assigning a
|
||||
// large value should fail.
|
||||
name: "barrier-struct",
|
||||
c: `#include <stdlib.h>
|
||||
struct s { char *a[10]; };
|
||||
struct s *f1() { return malloc(sizeof(struct s)); }
|
||||
void f2(struct s *p) {}`,
|
||||
body: `p := C.f1(); p.a = [10]*C.char{new(C.char)}; C.f2(p)`,
|
||||
fail: true,
|
||||
expensive: true,
|
||||
},
|
||||
{
|
||||
// Storing a Go pointer into C memory using a slice
|
||||
// copy should fail.
|
||||
name: "barrier-slice",
|
||||
c: `#include <stdlib.h>
|
||||
struct s { char *a[10]; };
|
||||
struct s *f1() { return malloc(sizeof(struct s)); }
|
||||
void f2(struct s *p) {}`,
|
||||
body: `p := C.f1(); copy(p.a[:], []*C.char{new(C.char)}); C.f2(p)`,
|
||||
fail: true,
|
||||
expensive: true,
|
||||
},
|
||||
{
|
||||
// A very large value uses a GC program, which is a
|
||||
// different code path.
|
||||
name: "barrier-gcprog-array",
|
||||
c: `#include <stdlib.h>
|
||||
struct s { char *a[32769]; };
|
||||
struct s *f1() { return malloc(sizeof(struct s)); }
|
||||
void f2(struct s *p) {}`,
|
||||
body: `p := C.f1(); p.a = [32769]*C.char{new(C.char)}; C.f2(p)`,
|
||||
fail: true,
|
||||
expensive: true,
|
||||
},
|
||||
{
|
||||
// Similar case, with a source on the heap.
|
||||
name: "barrier-gcprog-array-heap",
|
||||
c: `#include <stdlib.h>
|
||||
struct s { char *a[32769]; };
|
||||
struct s *f1() { return malloc(sizeof(struct s)); }
|
||||
void f2(struct s *p) {}
|
||||
void f3(void *p) {}`,
|
||||
imports: []string{"unsafe"},
|
||||
body: `p := C.f1(); n := &[32769]*C.char{new(C.char)}; p.a = *n; C.f2(p); n[0] = nil; C.f3(unsafe.Pointer(n))`,
|
||||
fail: true,
|
||||
expensive: true,
|
||||
},
|
||||
{
|
||||
// A GC program with a struct.
|
||||
name: "barrier-gcprog-struct",
|
||||
c: `#include <stdlib.h>
|
||||
struct s { char *a[32769]; };
|
||||
struct s2 { struct s f; };
|
||||
struct s2 *f1() { return malloc(sizeof(struct s2)); }
|
||||
void f2(struct s2 *p) {}`,
|
||||
body: `p := C.f1(); p.f = C.struct_s{[32769]*C.char{new(C.char)}}; C.f2(p)`,
|
||||
fail: true,
|
||||
expensive: true,
|
||||
},
|
||||
{
|
||||
// Similar case, with a source on the heap.
|
||||
name: "barrier-gcprog-struct-heap",
|
||||
c: `#include <stdlib.h>
|
||||
struct s { char *a[32769]; };
|
||||
struct s2 { struct s f; };
|
||||
struct s2 *f1() { return malloc(sizeof(struct s2)); }
|
||||
void f2(struct s2 *p) {}
|
||||
void f3(void *p) {}`,
|
||||
imports: []string{"unsafe"},
|
||||
body: `p := C.f1(); n := &C.struct_s{[32769]*C.char{new(C.char)}}; p.f = *n; C.f2(p); n.a[0] = nil; C.f3(unsafe.Pointer(n))`,
|
||||
fail: true,
|
||||
expensive: true,
|
||||
},
|
||||
{
|
||||
// Exported functions may not return Go pointers.
|
||||
name: "export1",
|
||||
c: `extern unsigned char *GoFn();`,
|
||||
support: `//export GoFn
|
||||
func GoFn() *byte { return new(byte) }`,
|
||||
body: `C.GoFn()`,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
// Returning a C pointer is fine.
|
||||
name: "exportok",
|
||||
c: `#include <stdlib.h>
|
||||
extern unsigned char *GoFn();`,
|
||||
support: `//export GoFn
|
||||
func GoFn() *byte { return (*byte)(C.malloc(1)) }`,
|
||||
body: `C.GoFn()`,
|
||||
},
|
||||
{
|
||||
// Passing a Go string is fine.
|
||||
name: "pass-string",
|
||||
c: `#include <stddef.h>
|
||||
typedef struct { const char *p; ptrdiff_t n; } gostring;
|
||||
gostring f(gostring s) { return s; }`,
|
||||
imports: []string{"unsafe"},
|
||||
body: `s := "a"; r := C.f(*(*C.gostring)(unsafe.Pointer(&s))); if *(*string)(unsafe.Pointer(&r)) != s { panic(r) }`,
|
||||
},
|
||||
{
|
||||
// Passing a slice of Go strings fails.
|
||||
name: "pass-string-slice",
|
||||
c: `void f(void *p) {}`,
|
||||
imports: []string{"strings", "unsafe"},
|
||||
support: `type S struct { a [1]string }`,
|
||||
body: `s := S{a:[1]string{strings.Repeat("a", 2)}}; C.f(unsafe.Pointer(&s.a[0]))`,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
// Exported functions may not return strings.
|
||||
name: "ret-string",
|
||||
c: `extern void f();`,
|
||||
imports: []string{"strings"},
|
||||
support: `//export GoStr
|
||||
func GoStr() string { return strings.Repeat("a", 2) }`,
|
||||
body: `C.f()`,
|
||||
extra: []extra{
|
||||
{
|
||||
"call.c",
|
||||
`#include <stddef.h>
|
||||
typedef struct { const char *p; ptrdiff_t n; } gostring;
|
||||
extern gostring GoStr();
|
||||
void f() { GoStr(); }`,
|
||||
},
|
||||
},
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
// Don't check non-pointer data.
|
||||
// Uses unsafe code to get a pointer we shouldn't check.
|
||||
// Although we use unsafe, the uintptr represents an integer
|
||||
// that happens to have the same representation as a pointer;
|
||||
// that is, we are testing something that is not unsafe.
|
||||
name: "ptrdata1",
|
||||
c: `#include <stdlib.h>
|
||||
void f(void* p) {}`,
|
||||
imports: []string{"unsafe"},
|
||||
support: `type S struct { p *int; a [8*8]byte; u uintptr }`,
|
||||
body: `i := 0; p := &S{u:uintptr(unsafe.Pointer(&i))}; q := (*S)(C.malloc(C.size_t(unsafe.Sizeof(*p)))); *q = *p; C.f(unsafe.Pointer(q))`,
|
||||
fail: false,
|
||||
},
|
||||
{
|
||||
// Like ptrdata1, but with a type that uses a GC program.
|
||||
name: "ptrdata2",
|
||||
c: `#include <stdlib.h>
|
||||
void f(void* p) {}`,
|
||||
imports: []string{"unsafe"},
|
||||
support: `type S struct { p *int; a [32769*8]byte; q *int; u uintptr }`,
|
||||
body: `i := 0; p := S{u:uintptr(unsafe.Pointer(&i))}; q := (*S)(C.malloc(C.size_t(unsafe.Sizeof(p)))); *q = p; C.f(unsafe.Pointer(q))`,
|
||||
fail: false,
|
||||
},
|
||||
{
|
||||
// Check deferred pointers when they are used, not
|
||||
// when the defer statement is run.
|
||||
name: "defer",
|
||||
c: `typedef struct s { int *p; } s; void f(s *ps) {}`,
|
||||
body: `p := &C.s{}; defer C.f(p); p.p = new(C.int)`,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
// Check a pointer to a union if the union has any
|
||||
// pointer fields.
|
||||
name: "union1",
|
||||
c: `typedef union { char **p; unsigned long i; } u; void f(u *pu) {}`,
|
||||
imports: []string{"unsafe"},
|
||||
body: `var b C.char; p := &b; C.f((*C.u)(unsafe.Pointer(&p)))`,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
// Don't check a pointer to a union if the union does
|
||||
// not have any pointer fields.
|
||||
// Like ptrdata1 above, the uintptr represents an
|
||||
// integer that happens to have the same
|
||||
// representation as a pointer.
|
||||
name: "union2",
|
||||
c: `typedef union { unsigned long i; } u; void f(u *pu) {}`,
|
||||
imports: []string{"unsafe"},
|
||||
body: `var b C.char; p := &b; C.f((*C.u)(unsafe.Pointer(&p)))`,
|
||||
fail: false,
|
||||
},
|
||||
}
|
||||
|
||||
func main() {
|
||||
os.Exit(doTests())
|
||||
}
|
||||
|
||||
func doTests() int {
|
||||
gopath, err := ioutil.TempDir("", "cgoerrors")
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return 2
|
||||
}
|
||||
defer os.RemoveAll(gopath)
|
||||
|
||||
if err := os.MkdirAll(filepath.Join(gopath, "src"), 0777); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return 2
|
||||
}
|
||||
|
||||
workers := runtime.NumCPU() + 1
|
||||
|
||||
var wg sync.WaitGroup
|
||||
c := make(chan int)
|
||||
errs := make(chan int)
|
||||
for i := 0; i < workers; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
worker(gopath, c, errs)
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
for i := range ptrTests {
|
||||
c <- i
|
||||
}
|
||||
close(c)
|
||||
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(errs)
|
||||
}()
|
||||
|
||||
tot := 0
|
||||
for e := range errs {
|
||||
tot += e
|
||||
}
|
||||
return tot
|
||||
}
|
||||
|
||||
func worker(gopath string, c, errs chan int) {
|
||||
e := 0
|
||||
for i := range c {
|
||||
if !doOne(gopath, i) {
|
||||
e++
|
||||
}
|
||||
}
|
||||
if e > 0 {
|
||||
errs <- e
|
||||
}
|
||||
}
|
||||
|
||||
func doOne(gopath string, i int) bool {
|
||||
t := &ptrTests[i]
|
||||
|
||||
dir := filepath.Join(gopath, "src", fmt.Sprintf("dir%d", i))
|
||||
if err := os.Mkdir(dir, 0777); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return false
|
||||
}
|
||||
|
||||
name := filepath.Join(dir, fmt.Sprintf("t%d.go", i))
|
||||
f, err := os.Create(name)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return false
|
||||
}
|
||||
|
||||
b := bufio.NewWriter(f)
|
||||
fmt.Fprintln(b, `package main`)
|
||||
fmt.Fprintln(b)
|
||||
fmt.Fprintln(b, `/*`)
|
||||
fmt.Fprintln(b, t.c)
|
||||
fmt.Fprintln(b, `*/`)
|
||||
fmt.Fprintln(b, `import "C"`)
|
||||
fmt.Fprintln(b)
|
||||
for _, imp := range t.imports {
|
||||
fmt.Fprintln(b, `import "`+imp+`"`)
|
||||
}
|
||||
if len(t.imports) > 0 {
|
||||
fmt.Fprintln(b)
|
||||
}
|
||||
if len(t.support) > 0 {
|
||||
fmt.Fprintln(b, t.support)
|
||||
fmt.Fprintln(b)
|
||||
}
|
||||
fmt.Fprintln(b, `func main() {`)
|
||||
fmt.Fprintln(b, t.body)
|
||||
fmt.Fprintln(b, `}`)
|
||||
|
||||
if err := b.Flush(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "flushing %s: %v\n", name, err)
|
||||
return false
|
||||
}
|
||||
if err := f.Close(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "closing %s: %v\n", name, err)
|
||||
return false
|
||||
}
|
||||
|
||||
for _, e := range t.extra {
|
||||
if err := ioutil.WriteFile(filepath.Join(dir, e.name), []byte(e.contents), 0644); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "writing %s: %v\n", e.name, err)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
ok := true
|
||||
|
||||
cmd := exec.Command("go", "build")
|
||||
cmd.Dir = dir
|
||||
cmd.Env = addEnv("GOPATH", gopath)
|
||||
buf, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "test %s failed to build: %v\n%s", t.name, err, buf)
|
||||
return false
|
||||
}
|
||||
|
||||
exe := filepath.Join(dir, filepath.Base(dir))
|
||||
cmd = exec.Command(exe)
|
||||
cmd.Dir = dir
|
||||
|
||||
if t.expensive {
|
||||
cmd.Env = cgocheckEnv("1")
|
||||
buf, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
var errbuf bytes.Buffer
|
||||
if t.fail {
|
||||
fmt.Fprintf(&errbuf, "test %s marked expensive but failed when not expensive: %v\n", t.name, err)
|
||||
} else {
|
||||
fmt.Fprintf(&errbuf, "test %s failed unexpectedly with GODEBUG=cgocheck=1: %v\n", t.name, err)
|
||||
}
|
||||
reportTestOutput(&errbuf, t.name, buf)
|
||||
os.Stderr.Write(errbuf.Bytes())
|
||||
ok = false
|
||||
}
|
||||
|
||||
cmd = exec.Command(exe)
|
||||
cmd.Dir = dir
|
||||
}
|
||||
|
||||
if t.expensive {
|
||||
cmd.Env = cgocheckEnv("2")
|
||||
}
|
||||
|
||||
buf, err = cmd.CombinedOutput()
|
||||
|
||||
if t.fail {
|
||||
if err == nil {
|
||||
var errbuf bytes.Buffer
|
||||
fmt.Fprintf(&errbuf, "test %s did not fail as expected\n", t.name)
|
||||
reportTestOutput(&errbuf, t.name, buf)
|
||||
os.Stderr.Write(errbuf.Bytes())
|
||||
ok = false
|
||||
} else if !bytes.Contains(buf, []byte("Go pointer")) {
|
||||
var errbuf bytes.Buffer
|
||||
fmt.Fprintf(&errbuf, "test %s output does not contain expected error (failed with %v)\n", t.name, err)
|
||||
reportTestOutput(&errbuf, t.name, buf)
|
||||
os.Stderr.Write(errbuf.Bytes())
|
||||
ok = false
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
var errbuf bytes.Buffer
|
||||
fmt.Fprintf(&errbuf, "test %s failed unexpectedly: %v\n", t.name, err)
|
||||
reportTestOutput(&errbuf, t.name, buf)
|
||||
os.Stderr.Write(errbuf.Bytes())
|
||||
ok = false
|
||||
}
|
||||
|
||||
if !t.expensive && ok {
|
||||
// Make sure it passes with the expensive checks.
|
||||
cmd := exec.Command(exe)
|
||||
cmd.Dir = dir
|
||||
cmd.Env = cgocheckEnv("2")
|
||||
buf, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
var errbuf bytes.Buffer
|
||||
fmt.Fprintf(&errbuf, "test %s failed unexpectedly with expensive checks: %v\n", t.name, err)
|
||||
reportTestOutput(&errbuf, t.name, buf)
|
||||
os.Stderr.Write(errbuf.Bytes())
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if t.fail && ok {
|
||||
cmd = exec.Command(exe)
|
||||
cmd.Dir = dir
|
||||
cmd.Env = cgocheckEnv("0")
|
||||
buf, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
var errbuf bytes.Buffer
|
||||
fmt.Fprintf(&errbuf, "test %s failed unexpectedly with GODEBUG=cgocheck=0: %v\n", t.name, err)
|
||||
reportTestOutput(&errbuf, t.name, buf)
|
||||
os.Stderr.Write(errbuf.Bytes())
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
|
||||
return ok
|
||||
}
|
||||
|
||||
func reportTestOutput(w io.Writer, name string, buf []byte) {
|
||||
fmt.Fprintf(w, "=== test %s output ===\n", name)
|
||||
fmt.Fprintf(w, "%s", buf)
|
||||
fmt.Fprintf(w, "=== end of test %s output ===\n", name)
|
||||
}
|
||||
|
||||
func cgocheckEnv(val string) []string {
|
||||
return addEnv("GODEBUG", "cgocheck="+val)
|
||||
}
|
||||
|
||||
func addEnv(key, val string) []string {
|
||||
env := []string{key + "=" + val}
|
||||
look := key + "="
|
||||
for _, e := range os.Environ() {
|
||||
if !strings.HasPrefix(e, look) {
|
||||
env = append(env, e)
|
||||
}
|
||||
}
|
||||
return env
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright 2013 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.
|
||||
|
||||
check() {
|
||||
file=$1
|
||||
line=$(grep -n 'ERROR HERE' $file | sed 's/:.*//')
|
||||
if [ "$line" = "" ]; then
|
||||
echo 1>&2 misc/cgo/errors/test.bash: BUG: cannot find ERROR HERE in $file
|
||||
exit 1
|
||||
fi
|
||||
expect $file $file:$line:
|
||||
}
|
||||
|
||||
expect() {
|
||||
file=$1
|
||||
shift
|
||||
if go build $file >errs 2>&1; then
|
||||
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected cgo to fail on $file but it succeeded
|
||||
exit 1
|
||||
fi
|
||||
if ! test -s errs; then
|
||||
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error output for $file but saw none
|
||||
exit 1
|
||||
fi
|
||||
for error; do
|
||||
if ! fgrep $error errs >/dev/null 2>&1; then
|
||||
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error output for $file to contain \"$error\" but saw:
|
||||
cat 1>&2 errs
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
check err1.go
|
||||
check err2.go
|
||||
check err3.go
|
||||
check issue7757.go
|
||||
check issue8442.go
|
||||
check issue11097a.go
|
||||
check issue11097b.go
|
||||
expect issue13129.go C.ushort
|
||||
check issue13423.go
|
||||
expect issue13635.go C.uchar C.schar C.ushort C.uint C.ulong C.longlong C.ulonglong C.complexfloat C.complexdouble
|
||||
check issue13830.go
|
||||
check issue16116.go
|
||||
check issue16591.go
|
||||
|
||||
if ! go build issue14669.go; then
|
||||
exit 1
|
||||
fi
|
||||
if ! CGO_CFLAGS="-O" go build issue14669.go; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! go run ptr.go; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# The malloc.go test should crash.
|
||||
rm -f malloc.out
|
||||
if go run malloc.go >malloc.out 2>&1; then
|
||||
echo '`go run malloc.go` succeeded unexpectedly'
|
||||
cat malloc.out
|
||||
rm -f malloc.out
|
||||
exit 1
|
||||
fi
|
||||
rm -f malloc.out
|
||||
|
||||
rm -rf errs _obj
|
||||
exit 0
|
|
@ -0,0 +1,9 @@
|
|||
! Copyright 2016 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.
|
||||
|
||||
function the_answer() result(j) bind(C)
|
||||
use iso_c_binding, only: c_int
|
||||
integer(c_int) :: j ! output
|
||||
j = 42
|
||||
end function the_answer
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright 2016 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 fortran
|
||||
|
||||
// int the_answer();
|
||||
import "C"
|
||||
|
||||
func TheAnswer() int {
|
||||
return int(C.the_answer())
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2016 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 fortran
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestFortran(t *testing.T) {
|
||||
if a := TheAnswer(); a != 42 {
|
||||
t.Errorf("Unexpected result for The Answer. Got: %d Want: 42", a)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
program HelloWorldF90
|
||||
write(*,*) "Hello World!"
|
||||
end program HelloWorldF90
|
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env bash
|
||||
# Copyright 2016 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.
|
||||
|
||||
# This directory is intended to test the use of Fortran with cgo.
|
||||
|
||||
set -e
|
||||
|
||||
FC=$1
|
||||
|
||||
goos=$(go env GOOS)
|
||||
|
||||
libext="so"
|
||||
if [ "$goos" == "darwin" ]; then
|
||||
libext="dylib"
|
||||
fi
|
||||
|
||||
case "$FC" in
|
||||
*gfortran*)
|
||||
libpath=$(dirname $($FC -print-file-name=libgfortran.$libext))
|
||||
export CGO_LDFLAGS="$CGO_LDFLAGS -Wl,-rpath,$libpath -L $libpath"
|
||||
;;
|
||||
esac
|
||||
|
||||
if ! $FC helloworld/helloworld.f90 -o main.exe >& /dev/null; then
|
||||
echo "skipping Fortran test: could not build helloworld.f90 with $FC"
|
||||
exit 0
|
||||
fi
|
||||
rm -f main.exe
|
||||
|
||||
status=0
|
||||
|
||||
if ! go test; then
|
||||
echo "FAIL: go test"
|
||||
status=1
|
||||
fi
|
||||
|
||||
exit $status
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright 2009 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.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Compute Fibonacci numbers with two goroutines
|
||||
// that pass integers back and forth. No actual
|
||||
// concurrency, just threads and synchronization
|
||||
// and foreign code on multiple pthreads.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
big "."
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func fibber(c chan *big.Int, out chan string, n int64) {
|
||||
// Keep the fibbers in dedicated operating system
|
||||
// threads, so that this program tests coordination
|
||||
// between pthreads and not just goroutines.
|
||||
runtime.LockOSThread()
|
||||
|
||||
i := big.NewInt(n)
|
||||
if n == 0 {
|
||||
c <- i
|
||||
}
|
||||
for {
|
||||
j := <-c
|
||||
out <- j.String()
|
||||
i.Add(i, j)
|
||||
c <- i
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
c := make(chan *big.Int)
|
||||
out := make(chan string)
|
||||
go fibber(c, out, 0)
|
||||
go fibber(c, out, 1)
|
||||
for i := 0; i < 200; i++ {
|
||||
println(<-out)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,380 @@
|
|||
// Copyright 2009 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.
|
||||
|
||||
/*
|
||||
An example of wrapping a C library in Go. This is the GNU
|
||||
multiprecision library gmp's integer type mpz_t wrapped to look like
|
||||
the Go package big's integer type Int.
|
||||
|
||||
This is a syntactically valid Go program—it can be parsed with the Go
|
||||
parser and processed by godoc—but it is not compiled directly by gc.
|
||||
Instead, a separate tool, cgo, processes it to produce three output
|
||||
files. The first two, 6g.go and 6c.c, are a Go source file for 6g and
|
||||
a C source file for 6c; both compile as part of the named package
|
||||
(gmp, in this example). The third, gcc.c, is a C source file for gcc;
|
||||
it compiles into a shared object (.so) that is dynamically linked into
|
||||
any 6.out that imports the first two files.
|
||||
|
||||
The stanza
|
||||
|
||||
// #include <gmp.h>
|
||||
import "C"
|
||||
|
||||
is a signal to cgo. The doc comment on the import of "C" provides
|
||||
additional context for the C file. Here it is just a single #include
|
||||
but it could contain arbitrary C definitions to be imported and used.
|
||||
|
||||
Cgo recognizes any use of a qualified identifier C.xxx and uses gcc to
|
||||
find the definition of xxx. If xxx is a type, cgo replaces C.xxx with
|
||||
a Go translation. C arithmetic types translate to precisely-sized Go
|
||||
arithmetic types. A C struct translates to a Go struct, field by
|
||||
field; unrepresentable fields are replaced with opaque byte arrays. A
|
||||
C union translates into a struct containing the first union member and
|
||||
perhaps additional padding. C arrays become Go arrays. C pointers
|
||||
become Go pointers. C function pointers become Go's uintptr.
|
||||
C void pointers become Go's unsafe.Pointer.
|
||||
|
||||
For example, mpz_t is defined in <gmp.h> as:
|
||||
|
||||
typedef unsigned long int mp_limb_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int _mp_alloc;
|
||||
int _mp_size;
|
||||
mp_limb_t *_mp_d;
|
||||
} __mpz_struct;
|
||||
|
||||
typedef __mpz_struct mpz_t[1];
|
||||
|
||||
Cgo generates:
|
||||
|
||||
type _C_int int32
|
||||
type _C_mp_limb_t uint64
|
||||
type _C___mpz_struct struct {
|
||||
_mp_alloc _C_int;
|
||||
_mp_size _C_int;
|
||||
_mp_d *_C_mp_limb_t;
|
||||
}
|
||||
type _C_mpz_t [1]_C___mpz_struct
|
||||
|
||||
and then replaces each occurrence of a type C.xxx with _C_xxx.
|
||||
|
||||
If xxx is data, cgo arranges for C.xxx to refer to the C variable,
|
||||
with the type translated as described above. To do this, cgo must
|
||||
introduce a Go variable that points at the C variable (the linker can
|
||||
be told to initialize this pointer). For example, if the gmp library
|
||||
provided
|
||||
|
||||
mpz_t zero;
|
||||
|
||||
then cgo would rewrite a reference to C.zero by introducing
|
||||
|
||||
var _C_zero *C.mpz_t
|
||||
|
||||
and then replacing all instances of C.zero with (*_C_zero).
|
||||
|
||||
Cgo's most interesting translation is for functions. If xxx is a C
|
||||
function, then cgo rewrites C.xxx into a new function _C_xxx that
|
||||
calls the C xxx in a standard pthread. The new function translates
|
||||
its arguments, calls xxx, and translates the return value.
|
||||
|
||||
Translation of parameters and the return value follows the type
|
||||
translation above except that arrays passed as parameters translate
|
||||
explicitly in Go to pointers to arrays, as they do (implicitly) in C.
|
||||
|
||||
Garbage collection is the big problem. It is fine for the Go world to
|
||||
have pointers into the C world and to free those pointers when they
|
||||
are no longer needed. To help, the Go code can define Go objects
|
||||
holding the C pointers and use runtime.SetFinalizer on those Go objects.
|
||||
|
||||
It is much more difficult for the C world to have pointers into the Go
|
||||
world, because the Go garbage collector is unaware of the memory
|
||||
allocated by C. The most important consideration is not to
|
||||
constrain future implementations, so the rule is that Go code can
|
||||
hand a Go pointer to C code but must separately arrange for
|
||||
Go to hang on to a reference to the pointer until C is done with it.
|
||||
*/
|
||||
package gmp
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lgmp
|
||||
#include <gmp.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// gmp 5.0.0+ changed the type of the 3rd argument to mp_bitcnt_t,
|
||||
// so, to support older versions, we wrap these two functions.
|
||||
void _mpz_mul_2exp(mpz_ptr a, mpz_ptr b, unsigned long n) {
|
||||
mpz_mul_2exp(a, b, n);
|
||||
}
|
||||
void _mpz_div_2exp(mpz_ptr a, mpz_ptr b, unsigned long n) {
|
||||
mpz_div_2exp(a, b, n);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"os"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
/*
|
||||
* one of a kind
|
||||
*/
|
||||
|
||||
// An Int represents a signed multi-precision integer.
|
||||
// The zero value for an Int represents the value 0.
|
||||
type Int struct {
|
||||
i C.mpz_t
|
||||
init bool
|
||||
}
|
||||
|
||||
// NewInt returns a new Int initialized to x.
|
||||
func NewInt(x int64) *Int { return new(Int).SetInt64(x) }
|
||||
|
||||
// Int promises that the zero value is a 0, but in gmp
|
||||
// the zero value is a crash. To bridge the gap, the
|
||||
// init bool says whether this is a valid gmp value.
|
||||
// doinit initializes z.i if it needs it. This is not inherent
|
||||
// to FFI, just a mismatch between Go's convention of
|
||||
// making zero values useful and gmp's decision not to.
|
||||
func (z *Int) doinit() {
|
||||
if z.init {
|
||||
return
|
||||
}
|
||||
z.init = true
|
||||
C.mpz_init(&z.i[0])
|
||||
}
|
||||
|
||||
// Bytes returns z's representation as a big-endian byte array.
|
||||
func (z *Int) Bytes() []byte {
|
||||
b := make([]byte, (z.Len()+7)/8)
|
||||
n := C.size_t(len(b))
|
||||
C.mpz_export(unsafe.Pointer(&b[0]), &n, 1, 1, 1, 0, &z.i[0])
|
||||
return b[0:n]
|
||||
}
|
||||
|
||||
// Len returns the length of z in bits. 0 is considered to have length 1.
|
||||
func (z *Int) Len() int {
|
||||
z.doinit()
|
||||
return int(C.mpz_sizeinbase(&z.i[0], 2))
|
||||
}
|
||||
|
||||
// Set sets z = x and returns z.
|
||||
func (z *Int) Set(x *Int) *Int {
|
||||
z.doinit()
|
||||
C.mpz_set(&z.i[0], &x.i[0])
|
||||
return z
|
||||
}
|
||||
|
||||
// SetBytes interprets b as the bytes of a big-endian integer
|
||||
// and sets z to that value.
|
||||
func (z *Int) SetBytes(b []byte) *Int {
|
||||
z.doinit()
|
||||
if len(b) == 0 {
|
||||
z.SetInt64(0)
|
||||
} else {
|
||||
C.mpz_import(&z.i[0], C.size_t(len(b)), 1, 1, 1, 0, unsafe.Pointer(&b[0]))
|
||||
}
|
||||
return z
|
||||
}
|
||||
|
||||
// SetInt64 sets z = x and returns z.
|
||||
func (z *Int) SetInt64(x int64) *Int {
|
||||
z.doinit()
|
||||
// TODO(rsc): more work on 32-bit platforms
|
||||
C.mpz_set_si(&z.i[0], C.long(x))
|
||||
return z
|
||||
}
|
||||
|
||||
// SetString interprets s as a number in the given base
|
||||
// and sets z to that value. The base must be in the range [2,36].
|
||||
// SetString returns an error if s cannot be parsed or the base is invalid.
|
||||
func (z *Int) SetString(s string, base int) error {
|
||||
z.doinit()
|
||||
if base < 2 || base > 36 {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
p := C.CString(s)
|
||||
defer C.free(unsafe.Pointer(p))
|
||||
if C.mpz_set_str(&z.i[0], p, C.int(base)) < 0 {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns the decimal representation of z.
|
||||
func (z *Int) String() string {
|
||||
if z == nil {
|
||||
return "nil"
|
||||
}
|
||||
z.doinit()
|
||||
p := C.mpz_get_str(nil, 10, &z.i[0])
|
||||
s := C.GoString(p)
|
||||
C.free(unsafe.Pointer(p))
|
||||
return s
|
||||
}
|
||||
|
||||
func (z *Int) destroy() {
|
||||
if z.init {
|
||||
C.mpz_clear(&z.i[0])
|
||||
}
|
||||
z.init = false
|
||||
}
|
||||
|
||||
/*
|
||||
* arithmetic
|
||||
*/
|
||||
|
||||
// Add sets z = x + y and returns z.
|
||||
func (z *Int) Add(x, y *Int) *Int {
|
||||
x.doinit()
|
||||
y.doinit()
|
||||
z.doinit()
|
||||
C.mpz_add(&z.i[0], &x.i[0], &y.i[0])
|
||||
return z
|
||||
}
|
||||
|
||||
// Sub sets z = x - y and returns z.
|
||||
func (z *Int) Sub(x, y *Int) *Int {
|
||||
x.doinit()
|
||||
y.doinit()
|
||||
z.doinit()
|
||||
C.mpz_sub(&z.i[0], &x.i[0], &y.i[0])
|
||||
return z
|
||||
}
|
||||
|
||||
// Mul sets z = x * y and returns z.
|
||||
func (z *Int) Mul(x, y *Int) *Int {
|
||||
x.doinit()
|
||||
y.doinit()
|
||||
z.doinit()
|
||||
C.mpz_mul(&z.i[0], &x.i[0], &y.i[0])
|
||||
return z
|
||||
}
|
||||
|
||||
// Div sets z = x / y, rounding toward zero, and returns z.
|
||||
func (z *Int) Div(x, y *Int) *Int {
|
||||
x.doinit()
|
||||
y.doinit()
|
||||
z.doinit()
|
||||
C.mpz_tdiv_q(&z.i[0], &x.i[0], &y.i[0])
|
||||
return z
|
||||
}
|
||||
|
||||
// Mod sets z = x % y and returns z.
|
||||
// Like the result of the Go % operator, z has the same sign as x.
|
||||
func (z *Int) Mod(x, y *Int) *Int {
|
||||
x.doinit()
|
||||
y.doinit()
|
||||
z.doinit()
|
||||
C.mpz_tdiv_r(&z.i[0], &x.i[0], &y.i[0])
|
||||
return z
|
||||
}
|
||||
|
||||
// Lsh sets z = x << s and returns z.
|
||||
func (z *Int) Lsh(x *Int, s uint) *Int {
|
||||
x.doinit()
|
||||
z.doinit()
|
||||
C._mpz_mul_2exp(&z.i[0], &x.i[0], C.ulong(s))
|
||||
return z
|
||||
}
|
||||
|
||||
// Rsh sets z = x >> s and returns z.
|
||||
func (z *Int) Rsh(x *Int, s uint) *Int {
|
||||
x.doinit()
|
||||
z.doinit()
|
||||
C._mpz_div_2exp(&z.i[0], &x.i[0], C.ulong(s))
|
||||
return z
|
||||
}
|
||||
|
||||
// Exp sets z = x^y % m and returns z.
|
||||
// If m == nil, Exp sets z = x^y.
|
||||
func (z *Int) Exp(x, y, m *Int) *Int {
|
||||
m.doinit()
|
||||
x.doinit()
|
||||
y.doinit()
|
||||
z.doinit()
|
||||
if m == nil {
|
||||
C.mpz_pow_ui(&z.i[0], &x.i[0], C.mpz_get_ui(&y.i[0]))
|
||||
} else {
|
||||
C.mpz_powm(&z.i[0], &x.i[0], &y.i[0], &m.i[0])
|
||||
}
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *Int) Int64() int64 {
|
||||
if !z.init {
|
||||
return 0
|
||||
}
|
||||
return int64(C.mpz_get_si(&z.i[0]))
|
||||
}
|
||||
|
||||
// Neg sets z = -x and returns z.
|
||||
func (z *Int) Neg(x *Int) *Int {
|
||||
x.doinit()
|
||||
z.doinit()
|
||||
C.mpz_neg(&z.i[0], &x.i[0])
|
||||
return z
|
||||
}
|
||||
|
||||
// Abs sets z to the absolute value of x and returns z.
|
||||
func (z *Int) Abs(x *Int) *Int {
|
||||
x.doinit()
|
||||
z.doinit()
|
||||
C.mpz_abs(&z.i[0], &x.i[0])
|
||||
return z
|
||||
}
|
||||
|
||||
/*
|
||||
* functions without a clear receiver
|
||||
*/
|
||||
|
||||
// CmpInt compares x and y. The result is
|
||||
//
|
||||
// -1 if x < y
|
||||
// 0 if x == y
|
||||
// +1 if x > y
|
||||
//
|
||||
func CmpInt(x, y *Int) int {
|
||||
x.doinit()
|
||||
y.doinit()
|
||||
switch cmp := C.mpz_cmp(&x.i[0], &y.i[0]); {
|
||||
case cmp < 0:
|
||||
return -1
|
||||
case cmp == 0:
|
||||
return 0
|
||||
}
|
||||
return +1
|
||||
}
|
||||
|
||||
// DivModInt sets q = x / y and r = x % y.
|
||||
func DivModInt(q, r, x, y *Int) {
|
||||
q.doinit()
|
||||
r.doinit()
|
||||
x.doinit()
|
||||
y.doinit()
|
||||
C.mpz_tdiv_qr(&q.i[0], &r.i[0], &x.i[0], &y.i[0])
|
||||
}
|
||||
|
||||
// GcdInt sets d to the greatest common divisor of a and b,
|
||||
// which must be positive numbers.
|
||||
// If x and y are not nil, GcdInt sets x and y such that d = a*x + b*y.
|
||||
// If either a or b is not positive, GcdInt sets d = x = y = 0.
|
||||
func GcdInt(d, x, y, a, b *Int) {
|
||||
d.doinit()
|
||||
x.doinit()
|
||||
y.doinit()
|
||||
a.doinit()
|
||||
b.doinit()
|
||||
C.mpz_gcdext(&d.i[0], &x.i[0], &y.i[0], &a.i[0], &b.i[0])
|
||||
}
|
||||
|
||||
// ProbablyPrime performs n Miller-Rabin tests to check whether z is prime.
|
||||
// If it returns true, z is prime with probability 1 - 1/4^n.
|
||||
// If it returns false, z is not prime.
|
||||
func (z *Int) ProbablyPrime(n int) bool {
|
||||
z.doinit()
|
||||
return int(C.mpz_probab_prime_p(&z.i[0], C.int(n))) > 0
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
// Copyright 2009 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.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
big "."
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var (
|
||||
tmp1 = big.NewInt(0)
|
||||
tmp2 = big.NewInt(0)
|
||||
numer = big.NewInt(1)
|
||||
accum = big.NewInt(0)
|
||||
denom = big.NewInt(1)
|
||||
ten = big.NewInt(10)
|
||||
)
|
||||
|
||||
func extractDigit() int64 {
|
||||
if big.CmpInt(numer, accum) > 0 {
|
||||
return -1
|
||||
}
|
||||
tmp1.Lsh(numer, 1).Add(tmp1, numer).Add(tmp1, accum)
|
||||
big.DivModInt(tmp1, tmp2, tmp1, denom)
|
||||
tmp2.Add(tmp2, numer)
|
||||
if big.CmpInt(tmp2, denom) >= 0 {
|
||||
return -1
|
||||
}
|
||||
return tmp1.Int64()
|
||||
}
|
||||
|
||||
func nextTerm(k int64) {
|
||||
y2 := k*2 + 1
|
||||
accum.Add(accum, tmp1.Lsh(numer, 1))
|
||||
accum.Mul(accum, tmp1.SetInt64(y2))
|
||||
numer.Mul(numer, tmp1.SetInt64(k))
|
||||
denom.Mul(denom, tmp1.SetInt64(y2))
|
||||
}
|
||||
|
||||
func eliminateDigit(d int64) {
|
||||
accum.Sub(accum, tmp1.Mul(denom, tmp1.SetInt64(d)))
|
||||
accum.Mul(accum, ten)
|
||||
numer.Mul(numer, ten)
|
||||
}
|
||||
|
||||
func main() {
|
||||
i := 0
|
||||
k := int64(0)
|
||||
for {
|
||||
d := int64(-1)
|
||||
for d < 0 {
|
||||
k++
|
||||
nextTerm(k)
|
||||
d = extractDigit()
|
||||
}
|
||||
eliminateDigit(d)
|
||||
fmt.Printf("%c", d+'0')
|
||||
|
||||
if i++; i%50 == 0 {
|
||||
fmt.Printf("\n")
|
||||
if i >= 1000 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("\n%d calls; bit sizes: %d %d %d\n", runtime.NumCgoCall(), numer.Len(), accum.Len(), denom.Len())
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright 2010 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.
|
||||
|
||||
#include <assert.h>
|
||||
#include "life.h"
|
||||
#include "_cgo_export.h"
|
||||
|
||||
const int MYCONST = 0;
|
||||
|
||||
// Do the actual manipulation of the life board in C. This could be
|
||||
// done easily in Go, we are just using C for demonstration
|
||||
// purposes.
|
||||
void
|
||||
Step(int x, int y, int *a, int *n)
|
||||
{
|
||||
struct GoStart_return r;
|
||||
|
||||
// Use Go to start 4 goroutines each of which handles 1/4 of the
|
||||
// board.
|
||||
r = GoStart(0, x, y, 0, x / 2, 0, y / 2, a, n);
|
||||
assert(r.r0 == 0 && r.r1 == 100); // test multiple returns
|
||||
r = GoStart(1, x, y, x / 2, x, 0, y / 2, a, n);
|
||||
assert(r.r0 == 1 && r.r1 == 101); // test multiple returns
|
||||
GoStart(2, x, y, 0, x / 2, y / 2, y, a, n);
|
||||
GoStart(3, x, y, x / 2, x, y / 2, y, a, n);
|
||||
GoWait(0);
|
||||
GoWait(1);
|
||||
GoWait(2);
|
||||
GoWait(3);
|
||||
}
|
||||
|
||||
// The actual computation. This is called in parallel.
|
||||
void
|
||||
DoStep(int xdim, int ydim, int xstart, int xend, int ystart, int yend, int *a, int *n)
|
||||
{
|
||||
int x, y, c, i, j;
|
||||
|
||||
for(x = xstart; x < xend; x++) {
|
||||
for(y = ystart; y < yend; y++) {
|
||||
c = 0;
|
||||
for(i = -1; i <= 1; i++) {
|
||||
for(j = -1; j <= 1; j++) {
|
||||
if(x+i >= 0 && x+i < xdim &&
|
||||
y+j >= 0 && y+j < ydim &&
|
||||
(i != 0 || j != 0))
|
||||
c += a[(x+i)*xdim + (y+j)] != 0;
|
||||
}
|
||||
}
|
||||
if(c == 3 || (c == 2 && a[x*xdim + y] != 0))
|
||||
n[x*xdim + y] = 1;
|
||||
else
|
||||
n[x*xdim + y] = 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// skip
|
||||
|
||||
// Copyright 2010 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 life
|
||||
|
||||
// #include "life.h"
|
||||
import "C"
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func Run(gen, x, y int, a []int32) {
|
||||
n := make([]int32, x*y)
|
||||
for i := 0; i < gen; i++ {
|
||||
C.Step(C.int(x), C.int(y), (*C.int)(unsafe.Pointer(&a[0])), (*C.int)(unsafe.Pointer(&n[0])))
|
||||
copy(a, n)
|
||||
}
|
||||
}
|
||||
|
||||
// Keep the channels visible from Go.
|
||||
var chans [4]chan bool
|
||||
|
||||
//export GoStart
|
||||
// Double return value is just for testing.
|
||||
func GoStart(i, xdim, ydim, xstart, xend, ystart, yend C.int, a *C.int, n *C.int) (int, int) {
|
||||
c := make(chan bool, int(C.MYCONST))
|
||||
go func() {
|
||||
C.DoStep(xdim, ydim, xstart, xend, ystart, yend, a, n)
|
||||
c <- true
|
||||
}()
|
||||
chans[i] = c
|
||||
return int(i), int(i + 100)
|
||||
}
|
||||
|
||||
//export GoWait
|
||||
func GoWait(i C.int) {
|
||||
<-chans[i]
|
||||
chans[i] = nil
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// Copyright 2010 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.
|
||||
|
||||
extern void Step(int, int, int *, int *);
|
||||
extern void DoStep(int, int, int, int, int, int, int *, int *);
|
||||
extern const int MYCONST;
|
|
@ -0,0 +1,48 @@
|
|||
// cmpout
|
||||
|
||||
// Copyright 2010 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.
|
||||
|
||||
// +build test_run
|
||||
|
||||
// Run the game of life in C using Go for parallelization.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"."
|
||||
"flag"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const MAXDIM = 100
|
||||
|
||||
var dim = flag.Int("dim", 16, "board dimensions")
|
||||
var gen = flag.Int("gen", 10, "generations")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
var a [MAXDIM * MAXDIM]int32
|
||||
for i := 2; i < *dim; i += 8 {
|
||||
for j := 2; j < *dim-3; j += 8 {
|
||||
for y := 0; y < 3; y++ {
|
||||
a[i**dim+j+y] = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
life.Run(*gen, *dim, *dim, a[:])
|
||||
|
||||
for i := 0; i < *dim; i++ {
|
||||
for j := 0; j < *dim; j++ {
|
||||
if a[i**dim+j] == 0 {
|
||||
fmt.Print(" ")
|
||||
} else {
|
||||
fmt.Print("X")
|
||||
}
|
||||
}
|
||||
fmt.Print("\n")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
|
||||
XXX XXX
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
XXX XXX
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright 2014 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.
|
||||
|
||||
// Test that -static works when not using cgo. This test is in
|
||||
// misc/cgo to take advantage of the testing framework support for
|
||||
// when -static is expected to work.
|
||||
|
||||
package nocgo
|
||||
|
||||
func NoCgo() int {
|
||||
c := make(chan int)
|
||||
|
||||
// The test is run with external linking, which means that
|
||||
// goroutines will be created via the runtime/cgo package.
|
||||
// Make sure that works.
|
||||
go func() {
|
||||
c <- 42
|
||||
}()
|
||||
|
||||
return <-c
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright 2014 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 nocgo
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestNop(t *testing.T) {
|
||||
i := NoCgo()
|
||||
if i != 42 {
|
||||
t.Errorf("got %d, want %d", i, 42)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// cmpout
|
||||
|
||||
// Copyright 2009 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.
|
||||
|
||||
// +build test_run
|
||||
|
||||
// Pass numbers along a chain of threads.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"strconv"
|
||||
|
||||
"../stdio"
|
||||
)
|
||||
|
||||
const N = 10
|
||||
const R = 5
|
||||
|
||||
func link(left chan<- int, right <-chan int) {
|
||||
// Keep the links in dedicated operating system
|
||||
// threads, so that this program tests coordination
|
||||
// between pthreads and not just goroutines.
|
||||
runtime.LockOSThread()
|
||||
for {
|
||||
v := <-right
|
||||
stdio.Stdout.WriteString(strconv.Itoa(v) + "\n")
|
||||
left <- 1 + v
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
leftmost := make(chan int)
|
||||
var left chan int
|
||||
right := leftmost
|
||||
for i := 0; i < N; i++ {
|
||||
left, right = right, make(chan int)
|
||||
go link(left, right)
|
||||
}
|
||||
for i := 0; i < R; i++ {
|
||||
right <- 0
|
||||
x := <-leftmost
|
||||
stdio.Stdout.WriteString(strconv.Itoa(x) + "\n")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
|
@ -0,0 +1,52 @@
|
|||
// cmpout
|
||||
|
||||
// Copyright 2009 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.
|
||||
|
||||
// +build test_run
|
||||
|
||||
// Compute Fibonacci numbers with two goroutines
|
||||
// that pass integers back and forth. No actual
|
||||
// concurrency, just threads and synchronization
|
||||
// and foreign code on multiple pthreads.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"strconv"
|
||||
|
||||
"../stdio"
|
||||
)
|
||||
|
||||
func fibber(c, out chan int64, i int64) {
|
||||
// Keep the fibbers in dedicated operating system
|
||||
// threads, so that this program tests coordination
|
||||
// between pthreads and not just goroutines.
|
||||
runtime.LockOSThread()
|
||||
|
||||
if i == 0 {
|
||||
c <- i
|
||||
}
|
||||
for {
|
||||
j := <-c
|
||||
stdio.Stdout.WriteString(strconv.FormatInt(j, 10) + "\n")
|
||||
out <- j
|
||||
<-out
|
||||
i += j
|
||||
c <- i
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
c := make(chan int64)
|
||||
out := make(chan int64)
|
||||
go fibber(c, out, 0)
|
||||
go fibber(c, out, 1)
|
||||
<-out
|
||||
for i := 0; i < 90; i++ {
|
||||
out <- 1
|
||||
<-out
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
0
|
||||
1
|
||||
1
|
||||
2
|
||||
3
|
||||
5
|
||||
8
|
||||
13
|
||||
21
|
||||
34
|
||||
55
|
||||
89
|
||||
144
|
||||
233
|
||||
377
|
||||
610
|
||||
987
|
||||
1597
|
||||
2584
|
||||
4181
|
||||
6765
|
||||
10946
|
||||
17711
|
||||
28657
|
||||
46368
|
||||
75025
|
||||
121393
|
||||
196418
|
||||
317811
|
||||
514229
|
||||
832040
|
||||
1346269
|
||||
2178309
|
||||
3524578
|
||||
5702887
|
||||
9227465
|
||||
14930352
|
||||
24157817
|
||||
39088169
|
||||
63245986
|
||||
102334155
|
||||
165580141
|
||||
267914296
|
||||
433494437
|
||||
701408733
|
||||
1134903170
|
||||
1836311903
|
||||
2971215073
|
||||
4807526976
|
||||
7778742049
|
||||
12586269025
|
||||
20365011074
|
||||
32951280099
|
||||
53316291173
|
||||
86267571272
|
||||
139583862445
|
||||
225851433717
|
||||
365435296162
|
||||
591286729879
|
||||
956722026041
|
||||
1548008755920
|
||||
2504730781961
|
||||
4052739537881
|
||||
6557470319842
|
||||
10610209857723
|
||||
17167680177565
|
||||
27777890035288
|
||||
44945570212853
|
||||
72723460248141
|
||||
117669030460994
|
||||
190392490709135
|
||||
308061521170129
|
||||
498454011879264
|
||||
806515533049393
|
||||
1304969544928657
|
||||
2111485077978050
|
||||
3416454622906707
|
||||
5527939700884757
|
||||
8944394323791464
|
||||
14472334024676221
|
||||
23416728348467685
|
||||
37889062373143906
|
||||
61305790721611591
|
||||
99194853094755497
|
||||
160500643816367088
|
||||
259695496911122585
|
||||
420196140727489673
|
||||
679891637638612258
|
||||
1100087778366101931
|
||||
1779979416004714189
|
||||
2880067194370816120
|
|
@ -0,0 +1,44 @@
|
|||
// skip
|
||||
|
||||
// Copyright 2009 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.
|
||||
|
||||
/*
|
||||
A trivial example of wrapping a C library in Go.
|
||||
For a more complex example and explanation,
|
||||
see ../gmp/gmp.go.
|
||||
*/
|
||||
|
||||
package stdio
|
||||
|
||||
/*
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
char* greeting = "hello, world";
|
||||
*/
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
type File C.FILE
|
||||
|
||||
// Test reference to library symbol.
|
||||
// Stdout and stderr are too special to be a reliable test.
|
||||
//var = C.environ
|
||||
|
||||
func (f *File) WriteString(s string) {
|
||||
p := C.CString(s)
|
||||
C.fputs(p, (*C.FILE)(f))
|
||||
C.free(unsafe.Pointer(p))
|
||||
f.Flush()
|
||||
}
|
||||
|
||||
func (f *File) Flush() {
|
||||
C.fflush((*C.FILE)(f))
|
||||
}
|
||||
|
||||
var Greeting = C.GoString(C.greeting)
|
||||
var Gbytes = C.GoBytes(unsafe.Pointer(C.greeting), C.int(len(Greeting)))
|
|
@ -0,0 +1,15 @@
|
|||
// cmpout
|
||||
|
||||
// Copyright 2009 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.
|
||||
|
||||
// +build test_run
|
||||
|
||||
package main
|
||||
|
||||
import "../stdio"
|
||||
|
||||
func main() {
|
||||
stdio.Stdout.WriteString(stdio.Greeting + "\n")
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
hello, world
|
|
@ -0,0 +1,150 @@
|
|||
* hello
|
||||
hello, world
|
||||
* fib
|
||||
0
|
||||
1
|
||||
1
|
||||
2
|
||||
3
|
||||
5
|
||||
8
|
||||
13
|
||||
21
|
||||
34
|
||||
55
|
||||
89
|
||||
144
|
||||
233
|
||||
377
|
||||
610
|
||||
987
|
||||
1597
|
||||
2584
|
||||
4181
|
||||
6765
|
||||
10946
|
||||
17711
|
||||
28657
|
||||
46368
|
||||
75025
|
||||
121393
|
||||
196418
|
||||
317811
|
||||
514229
|
||||
832040
|
||||
1346269
|
||||
2178309
|
||||
3524578
|
||||
5702887
|
||||
9227465
|
||||
14930352
|
||||
24157817
|
||||
39088169
|
||||
63245986
|
||||
102334155
|
||||
165580141
|
||||
267914296
|
||||
433494437
|
||||
701408733
|
||||
1134903170
|
||||
1836311903
|
||||
2971215073
|
||||
4807526976
|
||||
7778742049
|
||||
12586269025
|
||||
20365011074
|
||||
32951280099
|
||||
53316291173
|
||||
86267571272
|
||||
139583862445
|
||||
225851433717
|
||||
365435296162
|
||||
591286729879
|
||||
956722026041
|
||||
1548008755920
|
||||
2504730781961
|
||||
4052739537881
|
||||
6557470319842
|
||||
10610209857723
|
||||
17167680177565
|
||||
27777890035288
|
||||
44945570212853
|
||||
72723460248141
|
||||
117669030460994
|
||||
190392490709135
|
||||
308061521170129
|
||||
498454011879264
|
||||
806515533049393
|
||||
1304969544928657
|
||||
2111485077978050
|
||||
3416454622906707
|
||||
5527939700884757
|
||||
8944394323791464
|
||||
14472334024676221
|
||||
23416728348467685
|
||||
37889062373143906
|
||||
61305790721611591
|
||||
99194853094755497
|
||||
160500643816367088
|
||||
259695496911122585
|
||||
420196140727489673
|
||||
679891637638612258
|
||||
1100087778366101931
|
||||
1779979416004714189
|
||||
2880067194370816120
|
||||
* chain
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
|
@ -0,0 +1,22 @@
|
|||
// skip
|
||||
|
||||
// Copyright 2009 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 stdio
|
||||
|
||||
/*
|
||||
#include <stdio.h>
|
||||
|
||||
// on mingw, stderr and stdout are defined as &_iob[FILENO]
|
||||
// on netbsd, they are defined as &__sF[FILENO]
|
||||
// and cgo doesn't recognize them, so write a function to get them,
|
||||
// instead of depending on internals of libc implementation.
|
||||
FILE *getStdout(void) { return stdout; }
|
||||
FILE *getStderr(void) { return stderr; }
|
||||
*/
|
||||
import "C"
|
||||
|
||||
var Stdout = (*File)(C.getStdout())
|
||||
var Stderr = (*File)(C.getStderr())
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright 2010 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 cgotest
|
||||
|
||||
/*
|
||||
#include <stdio.h>
|
||||
|
||||
typedef unsigned char Uint8;
|
||||
typedef unsigned short Uint16;
|
||||
|
||||
typedef enum {
|
||||
MOD1 = 0x0000,
|
||||
MODX = 0x8000
|
||||
} SDLMod;
|
||||
|
||||
typedef enum {
|
||||
A = 1,
|
||||
B = 322,
|
||||
SDLK_LAST
|
||||
} SDLKey;
|
||||
|
||||
typedef struct SDL_keysym {
|
||||
Uint8 scancode;
|
||||
SDLKey sym;
|
||||
SDLMod mod;
|
||||
Uint16 unicode;
|
||||
} SDL_keysym;
|
||||
|
||||
typedef struct SDL_KeyboardEvent {
|
||||
Uint8 typ;
|
||||
Uint8 which;
|
||||
Uint8 state;
|
||||
SDL_keysym keysym;
|
||||
} SDL_KeyboardEvent;
|
||||
|
||||
void makeEvent(SDL_KeyboardEvent *event) {
|
||||
unsigned char *p;
|
||||
int i;
|
||||
|
||||
p = (unsigned char*)event;
|
||||
for (i=0; i<sizeof *event; i++) {
|
||||
p[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
int same(SDL_KeyboardEvent* e, Uint8 typ, Uint8 which, Uint8 state, Uint8 scan, SDLKey sym, SDLMod mod, Uint16 uni) {
|
||||
return e->typ == typ && e->which == which && e->state == state && e->keysym.scancode == scan && e->keysym.sym == sym && e->keysym.mod == mod && e->keysym.unicode == uni;
|
||||
}
|
||||
|
||||
void cTest(SDL_KeyboardEvent *event) {
|
||||
printf("C: %#x %#x %#x %#x %#x %#x %#x\n", event->typ, event->which, event->state,
|
||||
event->keysym.scancode, event->keysym.sym, event->keysym.mod, event->keysym.unicode);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testAlign(t *testing.T) {
|
||||
var evt C.SDL_KeyboardEvent
|
||||
C.makeEvent(&evt)
|
||||
if C.same(&evt, evt.typ, evt.which, evt.state, evt.keysym.scancode, evt.keysym.sym, evt.keysym.mod, evt.keysym.unicode) == 0 {
|
||||
t.Error("*** bad alignment")
|
||||
C.cTest(&evt)
|
||||
t.Errorf("Go: %#x %#x %#x %#x %#x %#x %#x\n",
|
||||
evt.typ, evt.which, evt.state, evt.keysym.scancode,
|
||||
evt.keysym.sym, evt.keysym.mod, evt.keysym.unicode)
|
||||
t.Error(evt)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
// API Compatibility Checks for cgo
|
||||
|
||||
package cgotest
|
||||
|
||||
// #include <stdlib.h>
|
||||
//
|
||||
// // Test for issue 17723.
|
||||
// typedef char *cstring_pointer;
|
||||
// static void cstring_pointer_fun(cstring_pointer dummy) { }
|
||||
//
|
||||
// const char *api_hello = "hello!";
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func testAPI() {
|
||||
var cs *C.char
|
||||
cs = C.CString("hello")
|
||||
defer C.free(unsafe.Pointer(cs))
|
||||
var s string
|
||||
s = C.GoString((*C.char)(C.api_hello))
|
||||
s = C.GoStringN((*C.char)(C.api_hello), C.int(6))
|
||||
var b []byte
|
||||
b = C.GoBytes(unsafe.Pointer(C.api_hello), C.int(6))
|
||||
_, _ = s, b
|
||||
C.cstring_pointer_fun(nil)
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2014 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 cgotest
|
||||
|
||||
import _ "unsafe"
|
||||
|
||||
//go:linkname lockedOSThread runtime.lockedOSThread
|
||||
//extern runtime_lockedOSThread
|
||||
func lockedOSThread() bool
|
|
@ -0,0 +1,167 @@
|
|||
// Copyright 2010 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.
|
||||
|
||||
// Basic test cases for cgo.
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define SHIFT(x, y) ((x)<<(y))
|
||||
#define KILO SHIFT(1, 10)
|
||||
#define UINT32VAL 0xc008427bU
|
||||
|
||||
enum E {
|
||||
Enum1 = 1,
|
||||
Enum2 = 2,
|
||||
};
|
||||
|
||||
typedef unsigned char cgo_uuid_t[20];
|
||||
|
||||
void uuid_generate(cgo_uuid_t x) {
|
||||
x[0] = 0;
|
||||
}
|
||||
|
||||
struct S {
|
||||
int x;
|
||||
};
|
||||
|
||||
extern enum E myConstFunc(struct S* const ctx, int const id, struct S **const filter);
|
||||
|
||||
enum E myConstFunc(struct S *const ctx, int const id, struct S **const filter) { return 0; }
|
||||
|
||||
// issue 1222
|
||||
typedef union {
|
||||
long align;
|
||||
} xxpthread_mutex_t;
|
||||
|
||||
struct ibv_async_event {
|
||||
union {
|
||||
int x;
|
||||
} element;
|
||||
};
|
||||
|
||||
struct ibv_context {
|
||||
xxpthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
int add(int x, int y) {
|
||||
return x+y;
|
||||
};
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"runtime"
|
||||
"syscall"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const EINVAL = C.EINVAL /* test #define */
|
||||
|
||||
var KILO = C.KILO
|
||||
|
||||
func uuidgen() {
|
||||
var uuid C.cgo_uuid_t
|
||||
C.uuid_generate(&uuid[0])
|
||||
}
|
||||
|
||||
func Strtol(s string, base int) (int, error) {
|
||||
p := C.CString(s)
|
||||
n, err := C.strtol(p, nil, C.int(base))
|
||||
C.free(unsafe.Pointer(p))
|
||||
return int(n), err
|
||||
}
|
||||
|
||||
func Atol(s string) int {
|
||||
p := C.CString(s)
|
||||
n := C.atol(p)
|
||||
C.free(unsafe.Pointer(p))
|
||||
return int(n)
|
||||
}
|
||||
|
||||
func testConst(t *testing.T) {
|
||||
C.myConstFunc(nil, 0, nil)
|
||||
}
|
||||
|
||||
func testEnum(t *testing.T) {
|
||||
if C.Enum1 != 1 || C.Enum2 != 2 {
|
||||
t.Error("bad enum", C.Enum1, C.Enum2)
|
||||
}
|
||||
}
|
||||
|
||||
func testAtol(t *testing.T) {
|
||||
l := Atol("123")
|
||||
if l != 123 {
|
||||
t.Error("Atol 123: ", l)
|
||||
}
|
||||
}
|
||||
|
||||
func testErrno(t *testing.T) {
|
||||
p := C.CString("no-such-file")
|
||||
m := C.CString("r")
|
||||
f, err := C.fopen(p, m)
|
||||
C.free(unsafe.Pointer(p))
|
||||
C.free(unsafe.Pointer(m))
|
||||
if err == nil {
|
||||
C.fclose(f)
|
||||
t.Fatalf("C.fopen: should fail")
|
||||
}
|
||||
if err != syscall.ENOENT {
|
||||
t.Fatalf("C.fopen: unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func testMultipleAssign(t *testing.T) {
|
||||
p := C.CString("234")
|
||||
n, m := C.strtol(p, nil, 345), C.strtol(p, nil, 10)
|
||||
if runtime.GOOS == "openbsd" {
|
||||
// Bug in OpenBSD strtol(3) - base > 36 succeeds.
|
||||
if (n != 0 && n != 239089) || m != 234 {
|
||||
t.Fatal("Strtol x2: ", n, m)
|
||||
}
|
||||
} else if n != 0 || m != 234 {
|
||||
t.Fatal("Strtol x2: ", n, m)
|
||||
}
|
||||
C.free(unsafe.Pointer(p))
|
||||
}
|
||||
|
||||
var (
|
||||
cuint = (C.uint)(0)
|
||||
culong C.ulong
|
||||
cchar C.char
|
||||
)
|
||||
|
||||
type Context struct {
|
||||
ctx *C.struct_ibv_context
|
||||
}
|
||||
|
||||
func benchCgoCall(b *testing.B) {
|
||||
const x = C.int(2)
|
||||
const y = C.int(3)
|
||||
for i := 0; i < b.N; i++ {
|
||||
C.add(x, y)
|
||||
}
|
||||
}
|
||||
|
||||
// Issue 2470.
|
||||
func testUnsignedInt(t *testing.T) {
|
||||
a := (int64)(C.UINT32VAL)
|
||||
b := (int64)(0xc008427b)
|
||||
if a != b {
|
||||
t.Errorf("Incorrect unsigned int - got %x, want %x", a, b)
|
||||
}
|
||||
}
|
||||
|
||||
// Static (build-time) test that syntax traversal visits all operands of s[i:j:k].
|
||||
func sliceOperands(array [2000]int) {
|
||||
_ = array[C.KILO:C.KILO:C.KILO] // no type error
|
||||
}
|
||||
|
||||
// set in cgo_thread_lock.go init
|
||||
var testThreadLockFunc = func(*testing.T) {}
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright 2014 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 cgotest
|
||||
|
||||
// Test that we have no more than one build ID. In the past we used
|
||||
// to generate a separate build ID for each package using cgo, and the
|
||||
// linker concatenated them all. We don't want that--we only want
|
||||
// one.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"debug/elf"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testBuildID(t *testing.T) {
|
||||
f, err := elf.Open("/proc/self/exe")
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
t.Skip("no /proc/self/exe")
|
||||
}
|
||||
t.Fatal("opening /proc/self/exe: ", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
c := 0
|
||||
for i, s := range f.Sections {
|
||||
if s.Type != elf.SHT_NOTE {
|
||||
continue
|
||||
}
|
||||
|
||||
d, err := s.Data()
|
||||
if err != nil {
|
||||
t.Logf("reading data of note section %d: %v", i, err)
|
||||
continue
|
||||
}
|
||||
|
||||
for len(d) > 0 {
|
||||
|
||||
// ELF standards differ as to the sizes in
|
||||
// note sections. Both the GNU linker and
|
||||
// gold always generate 32-bit sizes, so that
|
||||
// is what we assume here.
|
||||
|
||||
if len(d) < 12 {
|
||||
t.Logf("note section %d too short (%d < 12)", i, len(d))
|
||||
continue
|
||||
}
|
||||
|
||||
namesz := f.ByteOrder.Uint32(d)
|
||||
descsz := f.ByteOrder.Uint32(d[4:])
|
||||
typ := f.ByteOrder.Uint32(d[8:])
|
||||
|
||||
an := (namesz + 3) &^ 3
|
||||
ad := (descsz + 3) &^ 3
|
||||
|
||||
if int(12+an+ad) > len(d) {
|
||||
t.Logf("note section %d too short for header (%d < 12 + align(%d,4) + align(%d,4))", i, len(d), namesz, descsz)
|
||||
continue
|
||||
}
|
||||
|
||||
// 3 == NT_GNU_BUILD_ID
|
||||
if typ == 3 && namesz == 4 && bytes.Equal(d[12:16], []byte("GNU\000")) {
|
||||
c++
|
||||
}
|
||||
|
||||
d = d[12+an+ad:]
|
||||
}
|
||||
}
|
||||
|
||||
if c > 1 {
|
||||
t.Errorf("found %d build ID notes", c)
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,90 @@
|
|||
// Copyright 2011 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.
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include "_cgo_export.h"
|
||||
|
||||
void
|
||||
callback(void *f)
|
||||
{
|
||||
// use some stack space
|
||||
volatile char data[64*1024];
|
||||
|
||||
data[0] = 0;
|
||||
goCallback(f);
|
||||
data[sizeof(data)-1] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
callGoFoo(void)
|
||||
{
|
||||
extern void goFoo(void);
|
||||
goFoo();
|
||||
}
|
||||
|
||||
void
|
||||
IntoC(void)
|
||||
{
|
||||
BackIntoGo();
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
long long
|
||||
mysleep(int seconds) {
|
||||
long long st = GetTickCount();
|
||||
Sleep(1000 * seconds);
|
||||
return st;
|
||||
}
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
long long
|
||||
mysleep(int seconds) {
|
||||
long long st;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
st = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||
sleep(seconds);
|
||||
return st;
|
||||
}
|
||||
#endif
|
||||
|
||||
long long
|
||||
twoSleep(int n)
|
||||
{
|
||||
BackgroundSleep(n);
|
||||
return mysleep(n);
|
||||
}
|
||||
|
||||
void
|
||||
callGoStackCheck(void)
|
||||
{
|
||||
extern void goStackCheck(void);
|
||||
goStackCheck();
|
||||
}
|
||||
|
||||
int
|
||||
returnAfterGrow(void)
|
||||
{
|
||||
extern int goReturnVal(void);
|
||||
goReturnVal();
|
||||
return 123456;
|
||||
}
|
||||
|
||||
int
|
||||
returnAfterGrowFromGo(void)
|
||||
{
|
||||
extern int goReturnVal(void);
|
||||
return goReturnVal();
|
||||
}
|
||||
|
||||
void
|
||||
callGoWithString(void)
|
||||
{
|
||||
extern void goWithString(GoString);
|
||||
const char *str = "string passed from C to Go";
|
||||
goWithString((GoString){str, strlen(str)});
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
// +build gc
|
||||
|
||||
#include "_cgo_export.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Test calling panic from C. This is what SWIG does. */
|
||||
|
||||
extern void crosscall2(void (*fn)(void *, int), void *, int);
|
||||
extern void _cgo_panic(void *, int);
|
||||
extern void _cgo_allocate(void *, int);
|
||||
|
||||
void
|
||||
callPanic(void)
|
||||
{
|
||||
struct { const char *p; } a;
|
||||
a.p = "panic from C";
|
||||
crosscall2(_cgo_panic, &a, sizeof a);
|
||||
*(int*)1 = 1;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
// +build gccgo
|
||||
|
||||
#include "_cgo_export.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Test calling panic from C. This is what SWIG does. */
|
||||
|
||||
extern void _cgo_panic(const char *);
|
||||
extern void *_cgo_allocate(size_t);
|
||||
|
||||
void
|
||||
callPanic(void)
|
||||
{
|
||||
_cgo_panic("panic from C");
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
// Test that the #cgo CFLAGS directive works,
|
||||
// with and without platform filters.
|
||||
// See https://golang.org/issue/5224 for details.
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -DCOMMON_VALUE=123
|
||||
#cgo windows CFLAGS: -DIS_WINDOWS=1
|
||||
#cgo !windows CFLAGS: -DIS_WINDOWS=0
|
||||
int common = COMMON_VALUE;
|
||||
int is_windows = IS_WINDOWS;
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testCflags(t *testing.T) {
|
||||
is_windows := C.is_windows == 1
|
||||
if is_windows != (runtime.GOOS == "windows") {
|
||||
t.Errorf("is_windows: %v, runtime.GOOS: %s", is_windows, runtime.GOOS)
|
||||
}
|
||||
if C.common != 123 {
|
||||
t.Errorf("common: %v (expected 123)", C.common)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
// 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 cgotest
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestSetgid(t *testing.T) { testSetgid(t) }
|
||||
func Test6997(t *testing.T) { test6997(t) }
|
||||
func TestBuildID(t *testing.T) { testBuildID(t) }
|
||||
func Test9400(t *testing.T) { test9400(t) }
|
|
@ -0,0 +1,13 @@
|
|||
// 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 cgotest
|
||||
|
||||
import "testing"
|
||||
|
||||
// Stubs for tests that fails to build on Android
|
||||
func test6997(t *testing.T) {}
|
||||
func test3775(t *testing.T) {}
|
||||
func test8694(t *testing.T) {}
|
||||
func testSigaltstack(t *testing.T) {}
|
|
@ -0,0 +1,80 @@
|
|||
// Copyright 2011 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 cgotest
|
||||
|
||||
import "testing"
|
||||
|
||||
// The actual test functions are in non-_test.go files
|
||||
// so that they can use cgo (import "C").
|
||||
// These wrappers are here for gotest to find.
|
||||
|
||||
func TestAlign(t *testing.T) { testAlign(t) }
|
||||
func TestConst(t *testing.T) { testConst(t) }
|
||||
func TestEnum(t *testing.T) { testEnum(t) }
|
||||
func TestAtol(t *testing.T) { testAtol(t) }
|
||||
func TestErrno(t *testing.T) { testErrno(t) }
|
||||
func TestMultipleAssign(t *testing.T) { testMultipleAssign(t) }
|
||||
func TestUnsignedInt(t *testing.T) { testUnsignedInt(t) }
|
||||
func TestCallback(t *testing.T) { testCallback(t) }
|
||||
func TestCallbackGC(t *testing.T) { testCallbackGC(t) }
|
||||
func TestCallbackPanic(t *testing.T) { testCallbackPanic(t) }
|
||||
func TestCallbackPanicLoop(t *testing.T) { testCallbackPanicLoop(t) }
|
||||
func TestCallbackPanicLocked(t *testing.T) { testCallbackPanicLocked(t) }
|
||||
func TestPanicFromC(t *testing.T) { testPanicFromC(t) }
|
||||
func TestZeroArgCallback(t *testing.T) { testZeroArgCallback(t) }
|
||||
func TestBlocking(t *testing.T) { testBlocking(t) }
|
||||
func Test1328(t *testing.T) { test1328(t) }
|
||||
func TestParallelSleep(t *testing.T) { testParallelSleep(t) }
|
||||
func TestSetEnv(t *testing.T) { testSetEnv(t) }
|
||||
func TestHelpers(t *testing.T) { testHelpers(t) }
|
||||
func TestLibgcc(t *testing.T) { testLibgcc(t) }
|
||||
func Test1635(t *testing.T) { test1635(t) }
|
||||
func TestPrintf(t *testing.T) { testPrintf(t) }
|
||||
func Test4029(t *testing.T) { test4029(t) }
|
||||
func TestBoolAlign(t *testing.T) { testBoolAlign(t) }
|
||||
func Test3729(t *testing.T) { test3729(t) }
|
||||
func Test3775(t *testing.T) { test3775(t) }
|
||||
func TestCthread(t *testing.T) { testCthread(t) }
|
||||
func TestCallbackCallers(t *testing.T) { testCallbackCallers(t) }
|
||||
func Test5227(t *testing.T) { test5227(t) }
|
||||
func TestCflags(t *testing.T) { testCflags(t) }
|
||||
func Test5337(t *testing.T) { test5337(t) }
|
||||
func Test5548(t *testing.T) { test5548(t) }
|
||||
func Test5603(t *testing.T) { test5603(t) }
|
||||
func Test6833(t *testing.T) { test6833(t) }
|
||||
func Test3250(t *testing.T) { test3250(t) }
|
||||
func TestCallbackStack(t *testing.T) { testCallbackStack(t) }
|
||||
func TestFpVar(t *testing.T) { testFpVar(t) }
|
||||
func Test4339(t *testing.T) { test4339(t) }
|
||||
func Test6390(t *testing.T) { test6390(t) }
|
||||
func Test5986(t *testing.T) { test5986(t) }
|
||||
func Test7665(t *testing.T) { test7665(t) }
|
||||
func TestNaming(t *testing.T) { testNaming(t) }
|
||||
func Test7560(t *testing.T) { test7560(t) }
|
||||
func Test5242(t *testing.T) { test5242(t) }
|
||||
func Test8092(t *testing.T) { test8092(t) }
|
||||
func Test7978(t *testing.T) { test7978(t) }
|
||||
func Test8694(t *testing.T) { test8694(t) }
|
||||
func Test8517(t *testing.T) { test8517(t) }
|
||||
func Test8811(t *testing.T) { test8811(t) }
|
||||
func TestReturnAfterGrow(t *testing.T) { testReturnAfterGrow(t) }
|
||||
func TestReturnAfterGrowFromGo(t *testing.T) { testReturnAfterGrowFromGo(t) }
|
||||
func Test9026(t *testing.T) { test9026(t) }
|
||||
func Test9510(t *testing.T) { test9510(t) }
|
||||
func Test9557(t *testing.T) { test9557(t) }
|
||||
func Test10303(t *testing.T) { test10303(t, 10) }
|
||||
func Test11925(t *testing.T) { test11925(t) }
|
||||
func Test12030(t *testing.T) { test12030(t) }
|
||||
func TestGCC68255(t *testing.T) { testGCC68255(t) }
|
||||
func TestCallGoWithString(t *testing.T) { testCallGoWithString(t) }
|
||||
func Test14838(t *testing.T) { test14838(t) }
|
||||
func Test8756(t *testing.T) { test8756(t) }
|
||||
func Test17065(t *testing.T) { test17065(t) }
|
||||
func TestThreadLock(t *testing.T) { testThreadLockFunc(t) }
|
||||
func TestCheckConst(t *testing.T) { testCheckConst(t) }
|
||||
func Test17537(t *testing.T) { test17537(t) }
|
||||
func Test18126(t *testing.T) { test18126(t) }
|
||||
|
||||
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright 2016 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.
|
||||
|
||||
// +build linux,freebsd,openbsd
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
void Gosched(void);
|
||||
static int Ctid(void) { Gosched(); return syscall(SYS_gettid); }
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
//export Gosched
|
||||
func Gosched() {
|
||||
runtime.Gosched()
|
||||
}
|
||||
|
||||
func init() {
|
||||
testThreadLockFunc = testThreadLock
|
||||
}
|
||||
|
||||
func testThreadLock(t *testing.T) {
|
||||
stop := make(chan int)
|
||||
go func() {
|
||||
// We need the G continue running,
|
||||
// so the M has a chance to run this G.
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
return
|
||||
case <-time.After(time.Millisecond * 100):
|
||||
}
|
||||
}
|
||||
}()
|
||||
defer close(stop)
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
if C.int(syscall.Gettid()) != C.Ctid() {
|
||||
t.Fatalf("cgo has not locked OS thread")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2015 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.
|
||||
|
||||
// +build !windows
|
||||
|
||||
package cgotest
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestSigaltstack(t *testing.T) { testSigaltstack(t) }
|
||||
func TestSigprocmask(t *testing.T) { testSigprocmask(t) }
|
||||
func Test18146(t *testing.T) { test18146(t) }
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2016 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.
|
||||
|
||||
// Test a constant in conjunction with pointer checking.
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
|
||||
#define CheckConstVal 0
|
||||
|
||||
typedef struct {
|
||||
int *p;
|
||||
} CheckConstStruct;
|
||||
|
||||
static void CheckConstFunc(CheckConstStruct *p, int e) {
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func testCheckConst(t *testing.T) {
|
||||
// The test is that this compiles successfully.
|
||||
p := C.malloc(C.size_t(unsafe.Sizeof(C.int(0))))
|
||||
defer C.free(p)
|
||||
C.CheckConstFunc(&C.CheckConstStruct{(*C.int)(p)}, C.CheckConstVal)
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2016 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 cgotest
|
||||
|
||||
/*
|
||||
struct {
|
||||
float x;
|
||||
_Complex float y;
|
||||
} cplxAlign = { 3.14, 2.17 };
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestComplexAlign(t *testing.T) {
|
||||
if C.cplxAlign.x != 3.14 {
|
||||
t.Errorf("got %v, expected 3.14", C.cplxAlign.x)
|
||||
}
|
||||
if C.cplxAlign.y != 2.17 {
|
||||
t.Errorf("got %v, expected 2.17", C.cplxAlign.y)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2013 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 cgotest
|
||||
|
||||
// extern void doAdd(int, int);
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var sum struct {
|
||||
sync.Mutex
|
||||
i int
|
||||
}
|
||||
|
||||
//export Add
|
||||
func Add(x int) {
|
||||
defer func() {
|
||||
recover()
|
||||
}()
|
||||
sum.Lock()
|
||||
sum.i += x
|
||||
sum.Unlock()
|
||||
var p *int
|
||||
*p = 2
|
||||
}
|
||||
|
||||
func testCthread(t *testing.T) {
|
||||
if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
|
||||
t.Skip("the iOS exec wrapper is unable to properly handle the panic from Add")
|
||||
}
|
||||
sum.i = 0
|
||||
C.doAdd(10, 6)
|
||||
|
||||
want := 10 * (10 - 1) / 2 * 6
|
||||
if sum.i != want {
|
||||
t.Fatalf("sum=%d, want %d", sum.i, want)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
#include <pthread.h>
|
||||
#include "_cgo_export.h"
|
||||
|
||||
static void*
|
||||
addThread(void *p)
|
||||
{
|
||||
int i, max;
|
||||
|
||||
max = *(int*)p;
|
||||
for(i=0; i<max; i++)
|
||||
Add(i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
doAdd(int max, int nthread)
|
||||
{
|
||||
enum { MaxThread = 20 };
|
||||
int i;
|
||||
pthread_t thread_id[MaxThread];
|
||||
|
||||
if(nthread > MaxThread)
|
||||
nthread = MaxThread;
|
||||
for(i=0; i<nthread; i++)
|
||||
pthread_create(&thread_id[i], 0, addThread, &max);
|
||||
for(i=0; i<nthread; i++)
|
||||
pthread_join(thread_id[i], 0);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#include "_cgo_export.h"
|
||||
|
||||
__stdcall
|
||||
static unsigned int
|
||||
addThread(void *p)
|
||||
{
|
||||
int i, max;
|
||||
|
||||
max = *(int*)p;
|
||||
for(i=0; i<max; i++)
|
||||
Add(i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
doAdd(int max, int nthread)
|
||||
{
|
||||
enum { MaxThread = 20 };
|
||||
int i;
|
||||
uintptr_t thread_id[MaxThread];
|
||||
|
||||
if(nthread > MaxThread)
|
||||
nthread = MaxThread;
|
||||
for(i=0; i<nthread; i++)
|
||||
thread_id[i] = _beginthreadex(0, 0, addThread, &max, 0, 0);
|
||||
for(i=0; i<nthread; i++) {
|
||||
WaitForSingleObject((HANDLE)thread_id[i], INFINITE);
|
||||
CloseHandle((HANDLE)thread_id[i]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2010 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.
|
||||
|
||||
// This file contains test cases for cgo.
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
int base_symbol = 0;
|
||||
|
||||
#define alias_one base_symbol
|
||||
#define alias_two base_symbol
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import "fmt"
|
||||
|
||||
func duplicateSymbols() {
|
||||
fmt.Printf("%v %v %v\n", C.base_symbol, C.alias_one, C.alias_two)
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2011 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 cgotest
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// This is really an os package test but here for convenience.
|
||||
func testSetEnv(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
// Go uses SetEnvironmentVariable on windows. Howerver,
|
||||
// C runtime takes a *copy* at process startup of thei
|
||||
// OS environment, and stores it in environ/envp.
|
||||
// It is this copy that getenv/putenv manipulate.
|
||||
t.Logf("skipping test")
|
||||
return
|
||||
}
|
||||
const key = "CGO_OS_TEST_KEY"
|
||||
const val = "CGO_OS_TEST_VALUE"
|
||||
os.Setenv(key, val)
|
||||
keyc := C.CString(key)
|
||||
defer C.free(unsafe.Pointer(keyc))
|
||||
v := C.getenv(keyc)
|
||||
if uintptr(unsafe.Pointer(v)) == 0 {
|
||||
t.Fatal("getenv returned NULL")
|
||||
}
|
||||
vs := C.GoString(v)
|
||||
if vs != val {
|
||||
t.Fatalf("getenv() = %q; want %q", vs, val)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2011 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 cgotest
|
||||
|
||||
import "C"
|
||||
import "runtime"
|
||||
|
||||
//export ReturnIntLong
|
||||
func ReturnIntLong() (int, C.long) {
|
||||
return 1, 2
|
||||
}
|
||||
|
||||
//export gc
|
||||
func gc() {
|
||||
runtime.GC()
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
// This file contains test cases for cgo with function pointer variables.
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
typedef int (*intFunc) ();
|
||||
|
||||
int
|
||||
bridge_int_func(intFunc f)
|
||||
{
|
||||
return f();
|
||||
}
|
||||
|
||||
int fortytwo()
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
|
||||
*/
|
||||
import "C"
|
||||
import "testing"
|
||||
|
||||
func callBridge(f C.intFunc) int {
|
||||
return int(C.bridge_int_func(f))
|
||||
}
|
||||
|
||||
func callCBridge(f C.intFunc) C.int {
|
||||
return C.bridge_int_func(f)
|
||||
}
|
||||
|
||||
func testFpVar(t *testing.T) {
|
||||
const expected = 42
|
||||
f := C.intFunc(C.fortytwo)
|
||||
res1 := C.bridge_int_func(f)
|
||||
if r1 := int(res1); r1 != expected {
|
||||
t.Errorf("got %d, want %d", r1, expected)
|
||||
}
|
||||
res2 := callCBridge(f)
|
||||
if r2 := int(res2); r2 != expected {
|
||||
t.Errorf("got %d, want %d", r2, expected)
|
||||
}
|
||||
r3 := callBridge(f)
|
||||
if r3 != expected {
|
||||
t.Errorf("got %d, want %d", r3, expected)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2015 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 cgotest
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"./gcc68255"
|
||||
)
|
||||
|
||||
func testGCC68255(t *testing.T) {
|
||||
if !gcc68255.F() {
|
||||
t.Error("C global variable was not initialized")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2015 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.
|
||||
|
||||
// Test that it's OK to have C code that does nothing other than
|
||||
// initialize a global variable. This used to fail with gccgo.
|
||||
|
||||
package gcc68255
|
||||
|
||||
/*
|
||||
#include "c.h"
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func F() bool {
|
||||
return C.v != nil
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright 2015 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.
|
||||
|
||||
static void f(void) {
|
||||
}
|
||||
|
||||
void (*v)(void) = f;
|
|
@ -0,0 +1,5 @@
|
|||
// Copyright 2015 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.
|
||||
|
||||
extern void (*v)(void);
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright 2011 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 cgotest
|
||||
|
||||
// const char *greeting = "hello, world";
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const greeting = "hello, world"
|
||||
|
||||
type testPair struct {
|
||||
Name string
|
||||
Got, Want interface{}
|
||||
}
|
||||
|
||||
var testPairs = []testPair{
|
||||
{"GoString", C.GoString(C.greeting), greeting},
|
||||
{"GoStringN", C.GoStringN(C.greeting, 5), greeting[:5]},
|
||||
{"GoBytes", C.GoBytes(unsafe.Pointer(C.greeting), 5), []byte(greeting[:5])},
|
||||
}
|
||||
|
||||
func testHelpers(t *testing.T) {
|
||||
for _, pair := range testPairs {
|
||||
if !reflect.DeepEqual(pair.Got, pair.Want) {
|
||||
t.Errorf("%s: got %#v, want %#v", pair.Name, pair.Got, pair.Want)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright 2015 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.
|
||||
|
||||
// Issue 10303. Pointers passed to C were not marked as escaping (bug in cgo).
|
||||
|
||||
package cgotest
|
||||
|
||||
import "runtime"
|
||||
|
||||
/*
|
||||
typedef int *intptr;
|
||||
|
||||
void setintstar(int *x) {
|
||||
*x = 1;
|
||||
}
|
||||
|
||||
void setintptr(intptr x) {
|
||||
*x = 1;
|
||||
}
|
||||
|
||||
void setvoidptr(void *x) {
|
||||
*(int*)x = 1;
|
||||
}
|
||||
|
||||
typedef struct Struct Struct;
|
||||
struct Struct {
|
||||
int *P;
|
||||
};
|
||||
|
||||
void setstruct(Struct s) {
|
||||
*s.P = 1;
|
||||
}
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func test10303(t *testing.T, n int) {
|
||||
if runtime.Compiler == "gccgo" {
|
||||
t.Skip("gccgo permits C pointers on the stack")
|
||||
}
|
||||
|
||||
// Run at a few different stack depths just to avoid an unlucky pass
|
||||
// due to variables ending up on different pages.
|
||||
if n > 0 {
|
||||
test10303(t, n-1)
|
||||
}
|
||||
if t.Failed() {
|
||||
return
|
||||
}
|
||||
var x, y, z, v, si C.int
|
||||
var s C.Struct
|
||||
C.setintstar(&x)
|
||||
C.setintptr(&y)
|
||||
C.setvoidptr(unsafe.Pointer(&v))
|
||||
s.P = &si
|
||||
C.setstruct(s)
|
||||
|
||||
if uintptr(unsafe.Pointer(&x))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff {
|
||||
t.Error("C int* argument on stack")
|
||||
}
|
||||
if uintptr(unsafe.Pointer(&y))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff {
|
||||
t.Error("C intptr argument on stack")
|
||||
}
|
||||
if uintptr(unsafe.Pointer(&v))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff {
|
||||
t.Error("C void* argument on stack")
|
||||
}
|
||||
if uintptr(unsafe.Pointer(&si))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff {
|
||||
t.Error("C struct field pointer on stack")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2015 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.
|
||||
|
||||
// Issue 11925. Structs with zero-length trailing fields are now
|
||||
// padded by the Go compiler.
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
struct a11925 {
|
||||
int i;
|
||||
char a[0];
|
||||
char b[0];
|
||||
};
|
||||
|
||||
struct b11925 {
|
||||
int i;
|
||||
char a[0];
|
||||
char b[];
|
||||
};
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func test11925(t *testing.T) {
|
||||
if C.sizeof_struct_a11925 != unsafe.Sizeof(C.struct_a11925{}) {
|
||||
t.Errorf("size of a changed: C %d, Go %d", C.sizeof_struct_a11925, unsafe.Sizeof(C.struct_a11925{}))
|
||||
}
|
||||
if C.sizeof_struct_b11925 != unsafe.Sizeof(C.struct_b11925{}) {
|
||||
t.Errorf("size of b changed: C %d, Go %d", C.sizeof_struct_b11925, unsafe.Sizeof(C.struct_b11925{}))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright 2015 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.
|
||||
|
||||
// Issue 12030. sprintf is defined in both ntdll and msvcrt,
|
||||
// Normally we want the one in the msvcrt.
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
void issue12030conv(char *buf, double x) {
|
||||
sprintf(buf, "d=%g", x);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func test12030(t *testing.T) {
|
||||
buf := (*C.char)(C.malloc(256))
|
||||
defer C.free(unsafe.Pointer(buf))
|
||||
for _, f := range []float64{1.0, 2.0, 3.14} {
|
||||
C.issue12030conv(buf, C.double(f))
|
||||
got := C.GoString(buf)
|
||||
if want := fmt.Sprintf("d=%g", f); got != want {
|
||||
t.Fatalf("C.sprintf failed for %g: %q != %q", f, got, want)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright 2010 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.
|
||||
|
||||
// This file contains test cases for cgo.
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
// issue 1222
|
||||
typedef union {
|
||||
long align;
|
||||
} xxpthread_mutex_t;
|
||||
|
||||
struct ibv_async_event {
|
||||
union {
|
||||
int x;
|
||||
} element;
|
||||
};
|
||||
|
||||
struct ibv_context {
|
||||
xxpthread_mutex_t mutex;
|
||||
};
|
||||
*/
|
||||
import "C"
|
||||
|
||||
type AsyncEvent struct {
|
||||
event C.struct_ibv_async_event
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2011 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 cgotest
|
||||
|
||||
import "testing"
|
||||
|
||||
// extern void BackIntoGo(void);
|
||||
// void IntoC(void);
|
||||
import "C"
|
||||
|
||||
//export BackIntoGo
|
||||
func BackIntoGo() {
|
||||
x := 1
|
||||
|
||||
for i := 0; i < 10000; i++ {
|
||||
xvariadic(x)
|
||||
if x != 1 {
|
||||
panic("x is not 1?")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func xvariadic(x ...interface{}) {
|
||||
}
|
||||
|
||||
func test1328(t *testing.T) {
|
||||
C.IntoC()
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright 2015 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 cgotest
|
||||
|
||||
import "C"
|
||||
|
||||
var _ C.complexfloat
|
||||
var _ C.complexdouble
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2016 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.
|
||||
|
||||
// Issue 13930. Test that cgo's multiple-value special form for
|
||||
// C function calls works in variable declaration statements.
|
||||
|
||||
package cgotest
|
||||
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
|
||||
var _, _ = C.abs(0)
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2016 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.
|
||||
|
||||
// Issue 14838. add CBytes function
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
|
||||
int check_cbytes(char *b, size_t l) {
|
||||
int i;
|
||||
for (i = 0; i < l; i++) {
|
||||
if (b[i] != i) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func test14838(t *testing.T) {
|
||||
data := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||
cData := C.CBytes(data)
|
||||
defer C.free(cData)
|
||||
|
||||
if C.check_cbytes((*C.char)(cData), C.size_t(len(data))) == 0 {
|
||||
t.Fatalf("mismatched data: expected %v, got %v", data, (*(*[10]byte)(unsafe.Pointer(cData)))[:])
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright 2011 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 cgotest
|
||||
|
||||
/*
|
||||
// mysleep returns the absolute start time in ms.
|
||||
long long mysleep(int seconds);
|
||||
|
||||
// twoSleep returns the absolute start time of the first sleep
|
||||
// in ms.
|
||||
long long twoSleep(int);
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var sleepDone = make(chan int64)
|
||||
|
||||
// parallelSleep returns the absolute difference between the start time
|
||||
// of the two sleeps.
|
||||
func parallelSleep(n int) int64 {
|
||||
t := int64(C.twoSleep(C.int(n))) - <-sleepDone
|
||||
if t < 0 {
|
||||
return -t
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
//export BackgroundSleep
|
||||
func BackgroundSleep(n int32) {
|
||||
go func() {
|
||||
sleepDone <- int64(C.mysleep(C.int(n)))
|
||||
}()
|
||||
}
|
||||
|
||||
func testParallelSleep(t *testing.T) {
|
||||
sleepSec := 1
|
||||
dt := time.Duration(parallelSleep(sleepSec)) * time.Millisecond
|
||||
t.Logf("difference in start time for two sleep(%d) is %v", sleepSec, dt)
|
||||
// bug used to run sleeps in serial, producing a 2*sleepSec-second delay.
|
||||
// we detect if the start times of those sleeps are > 0.5*sleepSec-second.
|
||||
if dt >= time.Duration(sleepSec)*time.Second/2 {
|
||||
t.Fatalf("parallel %d-second sleeps slept for %f seconds", sleepSec, dt.Seconds())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
// 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 cgotest
|
||||
|
||||
/*
|
||||
// Mac OS X's gcc will generate scattered relocation 2/1 for
|
||||
// this function on Darwin/386, and 8l couldn't handle it.
|
||||
// this example is in issue 1635
|
||||
#include <stdio.h>
|
||||
void scatter() {
|
||||
void *p = scatter;
|
||||
printf("scatter = %p\n", p);
|
||||
}
|
||||
|
||||
// Adding this explicit extern declaration makes this a test for
|
||||
// https://gcc.gnu.org/PR68072 aka https://golang.org/issue/13344 .
|
||||
// It used to cause a cgo error when building with GCC 6.
|
||||
extern int hola;
|
||||
|
||||
// this example is in issue 3253
|
||||
int hola = 0;
|
||||
int testHola() { return hola; }
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import "testing"
|
||||
|
||||
func test1635(t *testing.T) {
|
||||
C.scatter()
|
||||
if v := C.hola; v != 0 {
|
||||
t.Fatalf("C.hola is %d, should be 0", v)
|
||||
}
|
||||
if v := C.testHola(); v != 0 {
|
||||
t.Fatalf("C.testHola() is %d, should be 0", v)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright 2016 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 cgotest
|
||||
|
||||
/*
|
||||
// Test that C symbols larger than a page play nicely with the race detector.
|
||||
// See issue 17065.
|
||||
|
||||
int ii[65537];
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var sink C.int
|
||||
|
||||
func test17065(t *testing.T) {
|
||||
if runtime.GOOS == "darwin" {
|
||||
t.Skip("broken on darwin; issue 17065")
|
||||
}
|
||||
for i := range C.ii {
|
||||
sink = C.ii[i]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright 2016 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.
|
||||
|
||||
// Issue 17537. The void* cast introduced by cgo to avoid problems
|
||||
// with const/volatile qualifiers breaks C preprocessor macros that
|
||||
// emulate functions.
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct {
|
||||
int i;
|
||||
} S17537;
|
||||
|
||||
int I17537(S17537 *p);
|
||||
|
||||
#define I17537(p) ((p)->i)
|
||||
|
||||
// Calling this function used to fail without the cast.
|
||||
const int F17537(const char **p) {
|
||||
return **p;
|
||||
}
|
||||
|
||||
// Calling this function used to trigger an error from the C compiler
|
||||
// (issue 18298).
|
||||
void F18298(const void *const *p) {
|
||||
}
|
||||
|
||||
// Test that conversions between typedefs work as they used to.
|
||||
typedef const void *T18298_1;
|
||||
struct S18298 { int i; };
|
||||
typedef const struct S18298 *T18298_2;
|
||||
void G18298(T18298_1 t) {
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import "testing"
|
||||
|
||||
func test17537(t *testing.T) {
|
||||
v := C.S17537{i: 17537}
|
||||
if got, want := C.I17537(&v), C.int(17537); got != want {
|
||||
t.Errorf("got %d, want %d", got, want)
|
||||
}
|
||||
|
||||
p := (*C.char)(C.malloc(1))
|
||||
*p = 17
|
||||
if got, want := C.F17537(&p), C.int(17); got != want {
|
||||
t.Errorf("got %d, want %d", got, want)
|
||||
}
|
||||
|
||||
C.F18298(nil)
|
||||
var v18298 C.T18298_2
|
||||
C.G18298(C.T18298_1(v18298))
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2016 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.
|
||||
|
||||
// Issue 18126: cgo check of void function returning errno.
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
|
||||
void Issue18126C(void **p) {
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func test18126(t *testing.T) {
|
||||
p := C.malloc(1)
|
||||
_, err := C.Issue18126C(&p)
|
||||
C.free(p)
|
||||
_ = err
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
// Copyright 2016 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.
|
||||
|
||||
// +build !windows
|
||||
|
||||
// Issue 18146: pthread_create failure during syscall.Exec.
|
||||
|
||||
package cgotest
|
||||
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func test18146(t *testing.T) {
|
||||
if runtime.GOOS == "darwin" {
|
||||
t.Skipf("skipping flaky test on %s; see golang.org/issue/18202", runtime.GOOS)
|
||||
}
|
||||
|
||||
if runtime.GOARCH == "mips" || runtime.GOARCH == "mips64" {
|
||||
t.Skipf("skipping on %s", runtime.GOARCH)
|
||||
}
|
||||
|
||||
attempts := 1000
|
||||
threads := 4
|
||||
|
||||
if testing.Short() {
|
||||
attempts = 100
|
||||
}
|
||||
|
||||
// Restrict the number of attempts based on RLIMIT_NPROC.
|
||||
// Tediously, RLIMIT_NPROC was left out of the syscall package,
|
||||
// probably because it is not in POSIX.1, so we define it here.
|
||||
// It is not defined on Solaris.
|
||||
var nproc int
|
||||
setNproc := true
|
||||
switch runtime.GOOS {
|
||||
default:
|
||||
setNproc = false
|
||||
case "linux":
|
||||
nproc = 6
|
||||
case "darwin", "dragonfly", "freebsd", "netbsd", "openbsd":
|
||||
nproc = 7
|
||||
}
|
||||
if setNproc {
|
||||
var rlim syscall.Rlimit
|
||||
if syscall.Getrlimit(nproc, &rlim) == nil {
|
||||
max := int(rlim.Cur) / (threads + 5)
|
||||
if attempts > max {
|
||||
t.Logf("lowering attempts from %d to %d for RLIMIT_NPROC", attempts, max)
|
||||
attempts = max
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if os.Getenv("test18146") == "exec" {
|
||||
runtime.GOMAXPROCS(1)
|
||||
for n := threads; n > 0; n-- {
|
||||
go func() {
|
||||
for {
|
||||
_ = md5.Sum([]byte("Hello, !"))
|
||||
}
|
||||
}()
|
||||
}
|
||||
runtime.GOMAXPROCS(threads)
|
||||
argv := append(os.Args, "-test.run=NoSuchTestExists")
|
||||
if err := syscall.Exec(os.Args[0], argv, os.Environ()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
var cmds []*exec.Cmd
|
||||
defer func() {
|
||||
for _, cmd := range cmds {
|
||||
cmd.Process.Kill()
|
||||
}
|
||||
}()
|
||||
|
||||
args := append(append([]string(nil), os.Args[1:]...), "-test.run=Test18146")
|
||||
for n := attempts; n > 0; n-- {
|
||||
cmd := exec.Command(os.Args[0], args...)
|
||||
cmd.Env = append(os.Environ(), "test18146=exec")
|
||||
buf := bytes.NewBuffer(nil)
|
||||
cmd.Stdout = buf
|
||||
cmd.Stderr = buf
|
||||
if err := cmd.Start(); err != nil {
|
||||
// We are starting so many processes that on
|
||||
// some systems (problem seen on Darwin,
|
||||
// Dragonfly, OpenBSD) the fork call will fail
|
||||
// with EAGAIN.
|
||||
if pe, ok := err.(*os.PathError); ok {
|
||||
err = pe.Err
|
||||
}
|
||||
if se, ok := err.(syscall.Errno); ok && (se == syscall.EAGAIN || se == syscall.EMFILE) {
|
||||
time.Sleep(time.Millisecond)
|
||||
continue
|
||||
}
|
||||
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
cmds = append(cmds, cmd)
|
||||
}
|
||||
|
||||
failures := 0
|
||||
for _, cmd := range cmds {
|
||||
err := cmd.Wait()
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
t.Errorf("syscall.Exec failed: %v\n%s", err, cmd.Stdout)
|
||||
failures++
|
||||
}
|
||||
|
||||
if failures > 0 {
|
||||
t.Logf("Failed %v of %v attempts.", failures, len(cmds))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
// Copyright 2011 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 cgotest
|
||||
|
||||
import "C"
|
||||
|
||||
//export exportbyte
|
||||
func exportbyte() byte {
|
||||
return 0
|
||||
}
|
||||
|
||||
//export exportbool
|
||||
func exportbool() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
//export exportrune
|
||||
func exportrune() rune {
|
||||
return 0
|
||||
}
|
||||
|
||||
//export exporterror
|
||||
func exporterror() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//export exportint
|
||||
func exportint() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
//export exportuint
|
||||
func exportuint() uint {
|
||||
return 0
|
||||
}
|
||||
|
||||
//export exportuintptr
|
||||
func exportuintptr() uintptr {
|
||||
return (uintptr)(0)
|
||||
}
|
||||
|
||||
//export exportint8
|
||||
func exportint8() int8 {
|
||||
return 0
|
||||
}
|
||||
|
||||
//export exportuint8
|
||||
func exportuint8() uint8 {
|
||||
return 0
|
||||
}
|
||||
|
||||
//export exportint16
|
||||
func exportint16() int16 {
|
||||
return 0
|
||||
}
|
||||
|
||||
//export exportuint16
|
||||
func exportuint16() uint16 {
|
||||
return 0
|
||||
}
|
||||
|
||||
//export exportint32
|
||||
func exportint32() int32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
//export exportuint32
|
||||
func exportuint32() uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
//export exportint64
|
||||
func exportint64() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
//export exportuint64
|
||||
func exportuint64() uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
//export exportfloat32
|
||||
func exportfloat32() float32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
//export exportfloat64
|
||||
func exportfloat64() float64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
//export exportcomplex64
|
||||
func exportcomplex64() complex64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
//export exportcomplex128
|
||||
func exportcomplex128() complex128 {
|
||||
return 0
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
// +build !windows
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static void *thread(void *p) {
|
||||
const int M = 100;
|
||||
int i;
|
||||
(void)p;
|
||||
for (i = 0; i < M; i++) {
|
||||
pthread_kill(pthread_self(), SIGCHLD);
|
||||
usleep(rand() % 20 + 5);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void testSendSIG() {
|
||||
const int N = 20;
|
||||
int i;
|
||||
pthread_t tid[N];
|
||||
for (i = 0; i < N; i++) {
|
||||
usleep(rand() % 200 + 100);
|
||||
pthread_create(&tid[i], 0, thread, NULL);
|
||||
}
|
||||
for (i = 0; i < N; i++)
|
||||
pthread_join(tid[i], 0);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func test3250(t *testing.T) {
|
||||
t.Skip("skipped, see golang.org/issue/5885")
|
||||
const (
|
||||
thres = 1
|
||||
sig = syscall.SIGCHLD
|
||||
)
|
||||
type result struct {
|
||||
n int
|
||||
sig os.Signal
|
||||
}
|
||||
var (
|
||||
sigCh = make(chan os.Signal, 10)
|
||||
waitStart = make(chan struct{})
|
||||
waitDone = make(chan result)
|
||||
)
|
||||
|
||||
signal.Notify(sigCh, sig)
|
||||
|
||||
go func() {
|
||||
n := 0
|
||||
alarm := time.After(time.Second * 3)
|
||||
for {
|
||||
select {
|
||||
case <-waitStart:
|
||||
waitStart = nil
|
||||
case v := <-sigCh:
|
||||
n++
|
||||
if v != sig || n > thres {
|
||||
waitDone <- result{n, v}
|
||||
return
|
||||
}
|
||||
case <-alarm:
|
||||
waitDone <- result{n, sig}
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
waitStart <- struct{}{}
|
||||
C.testSendSIG()
|
||||
r := <-waitDone
|
||||
if r.sig != sig {
|
||||
t.Fatalf("received signal %v, but want %v", r.sig, sig)
|
||||
}
|
||||
t.Logf("got %d signals\n", r.n)
|
||||
if r.n <= thres {
|
||||
t.Fatalf("expected more than %d", thres)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
// +build windows
|
||||
|
||||
package cgotest
|
||||
|
||||
import "testing"
|
||||
|
||||
func test3250(t *testing.T) {}
|
|
@ -0,0 +1,49 @@
|
|||
// 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 cgotest
|
||||
|
||||
/*
|
||||
// libgcc on ARM might be compiled as thumb code, but our 5l
|
||||
// can't handle that, so we have to disable this test on arm.
|
||||
#ifdef __ARMEL__
|
||||
#include <stdio.h>
|
||||
int vabs(int x) {
|
||||
puts("testLibgcc is disabled on ARM because 5l cannot handle thumb library.");
|
||||
return (x < 0) ? -x : x;
|
||||
}
|
||||
#elif defined(__arm64__) && defined(__clang__)
|
||||
#include <stdio.h>
|
||||
int vabs(int x) {
|
||||
puts("testLibgcc is disabled on ARM64 with clang due to lack of libgcc.");
|
||||
return (x < 0) ? -x : x;
|
||||
}
|
||||
#else
|
||||
int __absvsi2(int); // dummy prototype for libgcc function
|
||||
// we shouldn't name the function abs, as gcc might use
|
||||
// the builtin one.
|
||||
int vabs(int x) { return __absvsi2(x); }
|
||||
#endif
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import "testing"
|
||||
|
||||
func testLibgcc(t *testing.T) {
|
||||
var table = []struct {
|
||||
in, out C.int
|
||||
}{
|
||||
{0, 0},
|
||||
{1, 1},
|
||||
{-42, 42},
|
||||
{1000300, 1000300},
|
||||
{1 - 1<<31, 1<<31 - 1},
|
||||
}
|
||||
for _, v := range table {
|
||||
if o := C.vabs(v.in); o != v.out {
|
||||
t.Fatalf("abs(%d) got %d, should be %d", v.in, o, v.out)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
// 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.
|
||||
|
||||
// Issue 3729: cmd/cgo: access errno from void C function
|
||||
// void f(void) returns [0]byte, error in Go world.
|
||||
|
||||
// +build !windows
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
#include <errno.h>
|
||||
|
||||
void g(void) {
|
||||
errno = E2BIG;
|
||||
}
|
||||
|
||||
// try to pass some non-trivial arguments to function g2
|
||||
const char _expA = 0x42;
|
||||
const float _expB = 3.14159;
|
||||
const short _expC = 0x55aa;
|
||||
const int _expD = 0xdeadbeef;
|
||||
void g2(int x, char a, float b, short c, int d) {
|
||||
if (a == _expA && b == _expB && c == _expC && d == _expD)
|
||||
errno = x;
|
||||
else
|
||||
errno = -1;
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func test3729(t *testing.T) {
|
||||
_, e := C.g()
|
||||
if e != syscall.E2BIG {
|
||||
t.Errorf("got %q, expect %q", e, syscall.E2BIG)
|
||||
}
|
||||
_, e = C.g2(C.EINVAL, C._expA, C._expB, C._expC, C._expD)
|
||||
if e != syscall.EINVAL {
|
||||
t.Errorf("got %q, expect %q", e, syscall.EINVAL)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// 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.
|
||||
|
||||
// Issue 3729: cmd/cgo: access errno from void C function
|
||||
// void f(void) returns [0]byte, error in Go world.
|
||||
|
||||
// +build windows
|
||||
|
||||
package cgotest
|
||||
|
||||
import "testing"
|
||||
|
||||
func test3729(t *testing.T) {
|
||||
t.Log("skip errno test on Windows")
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// 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 cgotest
|
||||
|
||||
import "C"
|
||||
|
||||
//export exportSliceIn
|
||||
func exportSliceIn(s []byte) bool {
|
||||
return len(s) == cap(s)
|
||||
}
|
||||
|
||||
//export exportSliceOut
|
||||
func exportSliceOut() []byte {
|
||||
return []byte{1}
|
||||
}
|
||||
|
||||
//export exportSliceInOut
|
||||
func exportSliceInOut(s []byte) []byte {
|
||||
return s
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
// +build !android
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
void lockOSThreadCallback(void);
|
||||
inline static void lockOSThreadC(void)
|
||||
{
|
||||
lockOSThreadCallback();
|
||||
}
|
||||
int usleep(unsigned usec);
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Same as test3775 but run during init so that
|
||||
// there are two levels of internal runtime lock
|
||||
// (1 for init, 1 for cgo).
|
||||
// This would have been broken by CL 11663043.
|
||||
C.lockOSThreadC()
|
||||
}
|
||||
|
||||
func test3775(t *testing.T) {
|
||||
// Used to panic because of the UnlockOSThread below.
|
||||
C.lockOSThreadC()
|
||||
}
|
||||
|
||||
//export lockOSThreadCallback
|
||||
func lockOSThreadCallback() {
|
||||
runtime.LockOSThread()
|
||||
runtime.UnlockOSThread()
|
||||
go C.usleep(10000)
|
||||
runtime.Gosched()
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// 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 cgotest
|
||||
|
||||
// Test that cgo reserves enough stack space during cgo call.
|
||||
// See https://golang.org/issue/3945 for details.
|
||||
|
||||
// #include <stdio.h>
|
||||
//
|
||||
// void say() {
|
||||
// printf("%s from C\n", "hello");
|
||||
// }
|
||||
//
|
||||
import "C"
|
||||
|
||||
import "testing"
|
||||
|
||||
func testPrintf(t *testing.T) {
|
||||
C.say()
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright 2015 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.
|
||||
|
||||
// +build !windows
|
||||
|
||||
void call4029(void *arg) {
|
||||
void (*fn)(void) = arg;
|
||||
fn();
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
// 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.
|
||||
|
||||
// +build !windows
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
#include <dlfcn.h>
|
||||
#cgo linux LDFLAGS: -ldl
|
||||
|
||||
extern void call4029(void *arg);
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var callbacks int
|
||||
|
||||
//export IMPIsOpaque
|
||||
func IMPIsOpaque() {
|
||||
callbacks++
|
||||
}
|
||||
|
||||
//export IMPInitWithFrame
|
||||
func IMPInitWithFrame() {
|
||||
callbacks++
|
||||
}
|
||||
|
||||
//export IMPDrawRect
|
||||
func IMPDrawRect() {
|
||||
callbacks++
|
||||
}
|
||||
|
||||
//export IMPWindowResize
|
||||
func IMPWindowResize() {
|
||||
callbacks++
|
||||
}
|
||||
|
||||
func test4029(t *testing.T) {
|
||||
loadThySelf(t, "IMPWindowResize")
|
||||
loadThySelf(t, "IMPDrawRect")
|
||||
loadThySelf(t, "IMPInitWithFrame")
|
||||
loadThySelf(t, "IMPIsOpaque")
|
||||
if callbacks != 4 {
|
||||
t.Errorf("got %d callbacks, expected 4", callbacks)
|
||||
}
|
||||
}
|
||||
|
||||
func loadThySelf(t *testing.T, symbol string) {
|
||||
this_process := C.dlopen(nil, C.RTLD_NOW)
|
||||
if this_process == nil {
|
||||
t.Error("dlopen:", C.GoString(C.dlerror()))
|
||||
return
|
||||
}
|
||||
defer C.dlclose(this_process)
|
||||
|
||||
symbol_address := C.dlsym(this_process, C.CString(symbol))
|
||||
if symbol_address == nil {
|
||||
t.Error("dlsym:", C.GoString(C.dlerror()))
|
||||
return
|
||||
}
|
||||
t.Log(symbol, symbol_address)
|
||||
C.call4029(symbol_address)
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
// 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.
|
||||
|
||||
// +build windows
|
||||
|
||||
package cgotest
|
||||
|
||||
import "testing"
|
||||
|
||||
func test4029(t *testing.T) {
|
||||
}
|
|
@ -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 cgotest
|
||||
|
||||
/*
|
||||
typedef enum {
|
||||
A = 0,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
F,
|
||||
G,
|
||||
H,
|
||||
I,
|
||||
J,
|
||||
} issue4054a;
|
||||
*/
|
||||
import "C"
|
||||
|
||||
var issue4054a = []int{C.A, C.B, C.C, C.D, C.E, C.F, C.G, C.H, C.I, C.J}
|
|
@ -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 cgotest
|
||||
|
||||
/*
|
||||
typedef enum {
|
||||
A = 0,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
F,
|
||||
G,
|
||||
H,
|
||||
I,
|
||||
J,
|
||||
} issue4054b;
|
||||
*/
|
||||
import "C"
|
||||
|
||||
var issue4054b = []int{C.A, C.B, C.C, C.D, C.E, C.F, C.G, C.H, C.I, C.J}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue