summaryrefslogtreecommitdiff
path: root/misc/cgo
diff options
context:
space:
mode:
Diffstat (limited to 'misc/cgo')
-rw-r--r--misc/cgo/gmp/gmp.go2
-rw-r--r--misc/cgo/test/callback.go43
-rw-r--r--misc/cgo/test/cflags.go32
-rw-r--r--misc/cgo/test/cgo_test.go3
-rw-r--r--misc/cgo/test/cthread.go6
-rw-r--r--misc/cgo/test/issue4029.go9
-rw-r--r--misc/cgo/test/issue5227.go38
-rw-r--r--misc/cgo/testso/cgoso.c14
-rw-r--r--misc/cgo/testso/cgoso.go2
-rw-r--r--misc/cgo/testso/cgoso_c.c16
-rw-r--r--misc/cgo/testso/test.bat18
-rw-r--r--misc/cgo/testtls/tls.go28
-rw-r--r--misc/cgo/testtls/tls_test.go13
-rw-r--r--misc/cgo/testtls/tls_unix.c19
14 files changed, 232 insertions, 11 deletions
diff --git a/misc/cgo/gmp/gmp.go b/misc/cgo/gmp/gmp.go
index 3bcf99151..7b7a9b3c9 100644
--- a/misc/cgo/gmp/gmp.go
+++ b/misc/cgo/gmp/gmp.go
@@ -33,7 +33,7 @@ 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 pointer's become Go's unsafe.Pointer.
+C void pointers become Go's unsafe.Pointer.
For example, mpz_t is defined in <gmp.h> as:
diff --git a/misc/cgo/test/callback.go b/misc/cgo/test/callback.go
index 4f5d3f855..b6e2e3c1c 100644
--- a/misc/cgo/test/callback.go
+++ b/misc/cgo/test/callback.go
@@ -12,7 +12,9 @@ import "C"
import (
"./backdoor"
+ "path"
"runtime"
+ "strings"
"testing"
"unsafe"
)
@@ -136,3 +138,44 @@ func testBlocking(t *testing.T) {
}
})
}
+
+// Test that the stack can be unwound through a call out and call back
+// into Go.
+func testCallbackCallers(t *testing.T) {
+ pc := make([]uintptr, 100)
+ n := 0
+ name := []string{
+ "test.goCallback",
+ "runtime.cgocallbackg",
+ "runtime.cgocallback_gofunc",
+ "return",
+ "runtime.cgocall",
+ "test._Cfunc_callback",
+ "test.nestedCall",
+ "test.testCallbackCallers",
+ "test.TestCallbackCallers",
+ "testing.tRunner",
+ "runtime.goexit",
+ }
+ nestedCall(func() {
+ n = runtime.Callers(2, pc)
+ })
+ if n != len(name) {
+ t.Errorf("expected %d frames, got %d", len(name), n)
+ }
+ for i := 0; i < n; i++ {
+ f := runtime.FuncForPC(pc[i])
+ if f == nil {
+ t.Fatalf("expected non-nil Func for pc %p", pc[i])
+ }
+ fname := f.Name()
+ // Remove the prepended pathname from automatically
+ // generated cgo function names.
+ if strings.HasPrefix(fname, "_") {
+ fname = path.Base(f.Name()[1:])
+ }
+ if fname != name[i] {
+ t.Errorf("expected function name %s, got %s", name[i], fname)
+ }
+ }
+}
diff --git a/misc/cgo/test/cflags.go b/misc/cgo/test/cflags.go
new file mode 100644
index 000000000..24caab471
--- /dev/null
+++ b/misc/cgo/test/cflags.go
@@ -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 http://code.google.com/p/go/issues/detail?id=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)
+ }
+}
diff --git a/misc/cgo/test/cgo_test.go b/misc/cgo/test/cgo_test.go
index 536fa507a..56e1a0625 100644
--- a/misc/cgo/test/cgo_test.go
+++ b/misc/cgo/test/cgo_test.go
@@ -36,5 +36,8 @@ 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 BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
diff --git a/misc/cgo/test/cthread.go b/misc/cgo/test/cthread.go
index d918d033f..68d4a03ea 100644
--- a/misc/cgo/test/cthread.go
+++ b/misc/cgo/test/cthread.go
@@ -8,7 +8,6 @@ package cgotest
import "C"
import (
- "runtime"
"sync"
"testing"
)
@@ -31,10 +30,7 @@ func Add(x int) {
}
func testCthread(t *testing.T) {
- if runtime.GOARCH == "arm" {
- t.Skip("testCthread disabled on arm")
- }
-
+ sum.i = 0
C.doAdd(10, 6)
want := 10 * (10 - 1) / 2 * 6
diff --git a/misc/cgo/test/issue4029.go b/misc/cgo/test/issue4029.go
index 7495d38fe..b0385eb85 100644
--- a/misc/cgo/test/issue4029.go
+++ b/misc/cgo/test/issue4029.go
@@ -47,14 +47,15 @@ func test4029(t *testing.T) {
func loadThySelf(t *testing.T, symbol string) {
this_process := C.dlopen(nil, C.RTLD_NOW)
if this_process == nil {
- t.Fatal("dlopen:", C.GoString(C.dlerror()))
+ 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.Fatal("dlsym:", C.GoString(C.dlerror()))
- } else {
- t.Log(symbol, symbol_address)
+ t.Error("dlsym:", C.GoString(C.dlerror()))
+ return
}
+ t.Log(symbol, symbol_address)
}
diff --git a/misc/cgo/test/issue5227.go b/misc/cgo/test/issue5227.go
new file mode 100644
index 000000000..336c4c609
--- /dev/null
+++ b/misc/cgo/test/issue5227.go
@@ -0,0 +1,38 @@
+// 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.
+
+// Issue 5227: linker incorrectly treats common symbols and
+// leaves them undefined.
+
+package cgotest
+
+/*
+typedef struct {
+ int Count;
+} Fontinfo;
+
+Fontinfo SansTypeface;
+
+extern void init();
+
+Fontinfo loadfont() {
+ Fontinfo f = {0};
+ return f;
+}
+
+void init() {
+ SansTypeface = loadfont();
+}
+*/
+import "C"
+
+import "testing"
+
+func test5227(t *testing.T) {
+ C.init()
+}
+
+func selectfont() C.Fontinfo {
+ return C.SansTypeface
+}
diff --git a/misc/cgo/testso/cgoso.c b/misc/cgo/testso/cgoso.c
new file mode 100644
index 000000000..917f472d3
--- /dev/null
+++ b/misc/cgo/testso/cgoso.c
@@ -0,0 +1,14 @@
+// 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.
+
+#include "_cgo_export.h"
+
+#ifdef WIN32
+extern void setCallback(void *);
+void init() {
+ setCallback(goCallback);
+}
+#else
+void init() {}
+#endif
diff --git a/misc/cgo/testso/cgoso.go b/misc/cgo/testso/cgoso.go
index 44fb616c1..216cb1f05 100644
--- a/misc/cgo/testso/cgoso.go
+++ b/misc/cgo/testso/cgoso.go
@@ -6,11 +6,13 @@ package cgosotest
/*
#cgo LDFLAGS: -L. -lcgosotest
+void init(void);
void sofunc(void);
*/
import "C"
func Test() {
+ C.init()
C.sofunc()
}
diff --git a/misc/cgo/testso/cgoso_c.c b/misc/cgo/testso/cgoso_c.c
index 8c15a6b9f..27155c27f 100644
--- a/misc/cgo/testso/cgoso_c.c
+++ b/misc/cgo/testso/cgoso_c.c
@@ -4,8 +4,22 @@
// +build ignore
+#ifdef WIN32
+// A Windows DLL is unable to call an arbitrary function in
+// the main executable. Work around that by making the main
+// executable pass the callback function pointer to us.
+void (*goCallback)(void);
+__declspec(dllexport) void setCallback(void *f)
+{
+ goCallback = (void (*)())f;
+}
+__declspec(dllexport) void sofunc(void);
+#else
+extern void goCallback(void);
+void setCallback(void *f) { (void)f; }
+#endif
+
void sofunc(void)
{
- extern void goCallback(void);
goCallback();
}
diff --git a/misc/cgo/testso/test.bat b/misc/cgo/testso/test.bat
new file mode 100644
index 000000000..b8cc3842b
--- /dev/null
+++ b/misc/cgo/testso/test.bat
@@ -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.
+
+@echo off
+
+gcc -c cgoso_c.c
+gcc -shared -o libcgosotest.dll cgoso_c.o
+if not exist libcgosotest.dll goto fail
+go build main.go
+if not exist main.exe goto fail
+main.exe
+goto :end
+
+:fail
+set FAIL=1
+:end
+del /F cgoso_c.o libcgosotest.dll main.exe 2>NUL
diff --git a/misc/cgo/testtls/tls.go b/misc/cgo/testtls/tls.go
new file mode 100644
index 000000000..a9546a61c
--- /dev/null
+++ b/misc/cgo/testtls/tls.go
@@ -0,0 +1,28 @@
+// 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 cgotlstest
+
+// #include <pthread.h>
+// extern void setTLS(int);
+// extern int getTLS();
+import "C"
+
+import (
+ "runtime"
+ "testing"
+)
+
+func testTLS(t *testing.T) {
+ var keyVal C.int = 1234
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+ C.setTLS(C.int(keyVal))
+ storedVal := C.getTLS()
+
+ if storedVal != keyVal {
+ t.Fatalf("stored %d want %d", storedVal, keyVal)
+ }
+}
diff --git a/misc/cgo/testtls/tls_test.go b/misc/cgo/testtls/tls_test.go
new file mode 100644
index 000000000..3076c2d59
--- /dev/null
+++ b/misc/cgo/testtls/tls_test.go
@@ -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.
+
+// +build !windows
+
+package cgotlstest
+
+import "testing"
+
+func TestTLS(t *testing.T) {
+ testTLS(t)
+}
diff --git a/misc/cgo/testtls/tls_unix.c b/misc/cgo/testtls/tls_unix.c
new file mode 100644
index 000000000..545951631
--- /dev/null
+++ b/misc/cgo/testtls/tls_unix.c
@@ -0,0 +1,19 @@
+// 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.
+
+#include <pthread.h>
+
+static __thread int tls;
+
+void
+setTLS(int v)
+{
+ tls = v;
+}
+
+int
+getTLS()
+{
+ return tls;
+}