diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..82c2293 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,4 @@ +## Expected Behavior + +## Actual Behavior + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..4227089 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,14 @@ +## Description + +A few sentences describing the overall goals of the pull request's commits. + +## Designs + +If it's a feature, please write your code designs here. + +## Notes to reviewers + +Review the following things, including but not limit to: + +1. Design +2. Code (styles, magic...) \ No newline at end of file diff --git a/.gitignore b/.gitignore index 21bafdf..6e5cd1c 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,9 @@ _obj # macOS .DS_Store + +*.so +*.dll +*.obj +*.o +a.out diff --git a/SUMMARY.md b/SUMMARY.md index f7d9ea0..8365580 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -15,12 +15,16 @@ * [2.3. CGO编程基础](ch2-cgo/ch2-03-basic.md) * [2.4. CGO内存模型](ch2-cgo/ch2-04-memory.md) * [2.5. C++类包装](ch2-cgo/ch2-05-class.md) - * [2.6. 命令行工具和构建参数(TODO)](ch2-cgo/ch2-06-build.md) - * [2.7. 静态库和动态库(TODO)](ch2-cgo/ch2-07-dll.md) - * [2.8. 例子: 封装LevelDB(TODO)](ch2-cgo/ch2-08-leveldb.md) + * [2.6. CGO包的可移植性(TODO)](ch2-cgo/ch2-06-go-get-friendly.md) + * [2.7. Go实现Python模块(TODO)](ch2-cgo/ch2-07-py-module.md) + * [2.8. SWIG(TODO)](ch2-cgo/ch2-08-swig.md) * [2.9. 补充说明(TODO)](ch2-cgo/ch2-09-faq.md) +* [第三章 Go汇编语言](ch3-asm/readme.md) +* [第四章 Go和脚本语言](ch4-xlang/readme.md) * [第六章 Go和Web](ch6-web/readme.md) * [6.1. Web开发简介](ch6-web/ch6-01-introduction.md) + * [6.2. Router请求路由](ch6-web/ch6-02-router.md) + * [6.3. Middleware中间件](ch6-web/ch6-03-middleware.md) * [附录](appendix/readme.md) * [附录A: Go语言常见坑](appendix/appendix-a-trap.md) * [附录B: 参考资料](appendix/appendix-b-ref.md) diff --git a/ch1-basic/ch1-05-mem.md b/ch1-basic/ch1-05-mem.md index ed7712c..4ccb955 100644 --- a/ch1-basic/ch1-05-mem.md +++ b/ch1-basic/ch1-05-mem.md @@ -61,17 +61,21 @@ import ( "sync/atomic" ) -var total int64 +var total uint64 func worker(wg *sync.WaitGroup) { defer wg.Done() - for i := 0; i <= 100; i++ { + var i uint64 + for i = 0; i <= 100; i++ { atomic.AddUint64(&total, i) } } func main() { + var wg sync.WaitGroup + wg.Add(2) + go worker(&wg) go worker(&wg) wg.Wait() diff --git a/ch2-cgo/ch2-02-cgo-types.md b/ch2-cgo/ch2-02-cgo-types.md index e7c3b81..59395fe 100644 --- a/ch2-cgo/ch2-02-cgo-types.md +++ b/ch2-cgo/ch2-02-cgo-types.md @@ -59,6 +59,39 @@ uint64_t | C.uint64_t | uint64 前文说过,如果C语言的类型是由多个关键字组成,无法通过虚拟的“C”包直接访问。比如C语言的`unsigned short`不能直接通过`C.unsigned short`访问。但是,在``中通过使用C语言的`typedef`关键字将`unsigned short`重新定义为`uint16_t`一个单词的类型后,我们就可以通过`C.uint16_t`访问原来的`unsigned short`类型了。对于比较复杂的C语言类型,推荐使用`typedef`关键字提高一个规则的类型命名,这样更利于在CGO中访问。 +## Go 字符串和切片 + +在CGO生成的`_cgo_export.h`头文件中还会为Go语言特有的字符串、切片、字典、接口和管道等特有的数据类型生成对应的C语言类型: + +```c +typedef struct { const char *p; GoInt n; } GoString; +typedef void *GoMap; +typedef void *GoChan; +typedef struct { void *t; void *v; } GoInterface; +typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; +``` + +不过需要注意的是,其中只有Go语言的字符串和切片在CGO中有一定的使用价值,因为字符串和切片可以在Go调用C语言函数时马上使用。而其它的类型在C语言环境并无使用的价值,因为CGO并未针对这些类型提供相关的辅助函数,而且因为Go语言特有的内存模型的原因导致我们无法保持这些由Go语言管理的内存指针。 + +在导出的C语言函数中我们可以直接使用Go字符串和切片。假设有以下两个导出函数: + +```go +//export helloString +func helloString(s string) {} + +//export helloSlice +func helloSlice(s []byte) {} +``` + +CGO生成的`_cgo_export.h`头文件会包含以下的函数声明: + +```c +extern void helloString(GoString p0); +extern void helloSlice(GoSlice p0); +``` + +不过需要注意的是,如果使用了GoString类型会对`_cgo_export.h`头文件产生依赖,而这个头文件是动态输出的。更严谨的做法是为C语言函数接口定义严格的头文件,然后基于稳定的头文件实现代码。 + ## 结构体、联合、枚举类型 C语言的结构体、联合、枚举类型不能作为匿名成员被嵌入到Go语言的结构体中。在Go语言中,我们可以通过`C.struct_xxx`来访问C语言中定义的`struct xxx`结构体类型。结构体的内存布局按照C语言的通用对齐规则,在32位Go语言环境C语言结构体也按照32位对齐规则,在64位Go语言环境按照64位的对齐规则。对于指定了特殊对齐规则的结构体,无法在CGO中访问。 diff --git a/ch2-cgo/ch2-06-build.md b/ch2-cgo/ch2-06-build.md deleted file mode 100644 index 7b37439..0000000 --- a/ch2-cgo/ch2-06-build.md +++ /dev/null @@ -1,3 +0,0 @@ -# 2.6. 命令行工具和构建参数(TODO) - -TODO diff --git a/ch2-cgo/ch2-06-go-get-friendly.md b/ch2-cgo/ch2-06-go-get-friendly.md new file mode 100644 index 0000000..7f9525a --- /dev/null +++ b/ch2-cgo/ch2-06-go-get-friendly.md @@ -0,0 +1,19 @@ +# 2.6. CGO包的可移植性(TODO) + +TODO + + diff --git a/ch2-cgo/ch2-07-dll.md b/ch2-cgo/ch2-07-dll.md deleted file mode 100644 index 4438923..0000000 --- a/ch2-cgo/ch2-07-dll.md +++ /dev/null @@ -1,4 +0,0 @@ -# 2.7 静态库和动态库(TODO) - -TODO - diff --git a/ch2-cgo/ch2-07-py-module.md b/ch2-cgo/ch2-07-py-module.md new file mode 100644 index 0000000..65abd8c --- /dev/null +++ b/ch2-cgo/ch2-07-py-module.md @@ -0,0 +1,9 @@ +# 2.7 Go实现Python模块(TODO) + +TODO + + diff --git a/ch2-cgo/ch2-08-leveldb.md b/ch2-cgo/ch2-08-leveldb.md deleted file mode 100644 index d111388..0000000 --- a/ch2-cgo/ch2-08-leveldb.md +++ /dev/null @@ -1,3 +0,0 @@ -# 2.8. 封装LevelDB(TODO) - -TODO diff --git a/ch2-cgo/ch2-08-swig.md b/ch2-cgo/ch2-08-swig.md new file mode 100644 index 0000000..fa74b72 --- /dev/null +++ b/ch2-cgo/ch2-08-swig.md @@ -0,0 +1,7 @@ +# 2.8. SWIG(TODO) + +TODO + + diff --git a/ch2-cgo/ch2-09-faq.md b/ch2-cgo/ch2-09-faq.md index 95b6fae..264511a 100644 --- a/ch2-cgo/ch2-09-faq.md +++ b/ch2-cgo/ch2-09-faq.md @@ -1,3 +1,11 @@ # 2.9. 补充说明(TODO) TODO + + diff --git a/ch3-asm/readme.md b/ch3-asm/readme.md new file mode 100644 index 0000000..20f06e0 --- /dev/null +++ b/ch3-asm/readme.md @@ -0,0 +1,3 @@ +# 第三章 Go汇编语言 + +TODO diff --git a/ch4-xlang/readme.md b/ch4-xlang/readme.md new file mode 100644 index 0000000..08ff909 --- /dev/null +++ b/ch4-xlang/readme.md @@ -0,0 +1,3 @@ +# 第四章 Go和脚本语言 + +TODO diff --git a/examples/ch2-07/hello-py/Makefile b/examples/ch2-07/hello-py/Makefile new file mode 100644 index 0000000..2c0e6a6 --- /dev/null +++ b/examples/ch2-07/hello-py/Makefile @@ -0,0 +1,12 @@ +default: + go build -buildmode=c-shared -o gopkg.so main.go + python3 -c 'import gopkg; print(gopkg.system("time"))' + python3 -c 'import gopkg; print(gopkg.sum(2, 3))' + +clean: + -rm *.so + +# PKG_CONFIG=python3-config go build -buildmode=c-shared -o say-hello.so main.go +# python3-config --ldflags +# python3-config --include + diff --git a/examples/ch2-07/hello-py/gopkg.h b/examples/ch2-07/hello-py/gopkg.h new file mode 100644 index 0000000..a5f4a5a --- /dev/null +++ b/examples/ch2-07/hello-py/gopkg.h @@ -0,0 +1,106 @@ +/* Created by "go tool cgo" - DO NOT EDIT. */ + +/* package command-line-arguments */ + +/* Start of preamble from import "C" comments. */ + + +#line 3 "/Users/chai/go/src/github.com/chai2010/advanced-go-programming-book/examples/ch2-07/hello-py/main.go" + +// macOS: +// python3-config --cflags +// python3-config --ldflags + + + +// linux + + +// windows +// should generate libpython3.a from python3.lib + +#define Py_LIMITED_API +#include + +static PyObject * +spam_system(PyObject *self, PyObject *args) { + const char *command; + if (!PyArg_ParseTuple(args, "s", &command)) { + return NULL; + } + + int status = system(command); + return PyLong_FromLong(status); +} + +extern PyObject *sum(PyObject *self, PyObject *args); + +static PyMethodDef modMethods[] = { + {"system", spam_system, METH_VARARGS, "Execute a shell command."}, + {"sum", sum, METH_VARARGS, "Execute a shell command."}, + {NULL, NULL, 0, NULL} +}; + +static PyObject* PyInit_gopkg_(void) { + static struct PyModuleDef module = { + PyModuleDef_HEAD_INIT, "gopkg", NULL, -1, modMethods, + }; + return (void*)PyModule_Create(&module); +} + +#line 1 "cgo-generated-wrapper" + + +/* End of preamble from import "C" comments. */ + + +/* Start of boilerplate cgo prologue. */ +#line 1 "cgo-gcc-export-header-prolog" + +#ifndef GO_CGO_PROLOGUE_H +#define GO_CGO_PROLOGUE_H + +typedef signed char GoInt8; +typedef unsigned char GoUint8; +typedef short GoInt16; +typedef unsigned short GoUint16; +typedef int GoInt32; +typedef unsigned int GoUint32; +typedef long long GoInt64; +typedef unsigned long long GoUint64; +typedef GoInt64 GoInt; +typedef GoUint64 GoUint; +typedef __SIZE_TYPE__ GoUintptr; +typedef float GoFloat32; +typedef double GoFloat64; +typedef float _Complex GoComplex64; +typedef double _Complex GoComplex128; + +/* + static assertion to make sure the file is being used on architecture + at least with matching size of GoInt. +*/ +typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; + +typedef struct { const char *p; GoInt n; } GoString; +typedef void *GoMap; +typedef void *GoChan; +typedef struct { void *t; void *v; } GoInterface; +typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; + +#endif + +/* End of boilerplate cgo prologue. */ + +#ifdef __cplusplus +extern "C" { +#endif + + +extern PyObject* sum(PyObject* p0, PyObject* p1); + +extern PyObject* PyInit_gopkg(); + +#ifdef __cplusplus +} +#endif diff --git a/examples/ch2-07/hello-py/main.go b/examples/ch2-07/hello-py/main.go new file mode 100644 index 0000000..737317b --- /dev/null +++ b/examples/ch2-07/hello-py/main.go @@ -0,0 +1,66 @@ +package main + +/* +// macOS: +// python3-config --cflags +// python3-config --ldflags +#cgo darwin CFLAGS: -I/Library/Frameworks/Python.framework/Versions/3.6/include/python3.6m -I/Library/Frameworks/Python.framework/Versions/3.6/include/python3.6m -fno-strict-aliasing -Wsign-compare -fno-common -dynamic -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -g +#cgo darwin LDFLAGS: -L/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/config-3.6m-darwin -lpython3.6m -ldl -framework CoreFoundation + +// linux +#cgo linux pkg-config: python3 + +// windows +// should generate libpython3.a from python3.lib + +#define Py_LIMITED_API +#include + +static PyObject * +spam_system(PyObject *self, PyObject *args) { + const char *command; + if (!PyArg_ParseTuple(args, "s", &command)) { + return NULL; + } + + int status = system(command); + return PyLong_FromLong(status); +} + +extern PyObject *sum(PyObject *self, PyObject *args); + +static PyMethodDef modMethods[] = { + {"system", spam_system, METH_VARARGS, "Execute a shell command."}, + {"sum", sum, METH_VARARGS, "Execute a shell command."}, + {NULL, NULL, 0, NULL} +}; + +static PyObject* PyInit_gopkg_(void) { + static struct PyModuleDef module = { + PyModuleDef_HEAD_INIT, "gopkg", NULL, -1, modMethods, + }; + return (void*)PyModule_Create(&module); +} +*/ +import "C" + +import ( + "fmt" +) + +func main() {} + +// export SayHello +func SayHello(name *C.char) { + fmt.Printf("hello %s!\n", C.GoString(name)) +} + +//export sum +func sum(self, args *C.PyObject) *C.PyObject { + return C.PyLong_FromLongLong(9527) // TODO +} + +//export PyInit_gopkg +func PyInit_gopkg() *C.PyObject { + return C.PyInit_gopkg_() +} diff --git a/examples/ch2-07/hello-so/Makefile b/examples/ch2-07/hello-so/Makefile new file mode 100644 index 0000000..f76a8b0 --- /dev/null +++ b/examples/ch2-07/hello-so/Makefile @@ -0,0 +1,11 @@ +default: + go build -buildmode=c-shared -o say-hello.so main.go + gcc -Wall _test_so.c ./say-hello.so + ./a.out + +run-py3: + python3 hello.py + +clean: + -rm *.so + -rm *.out diff --git a/examples/ch2-07/hello-so/_test_so.c b/examples/ch2-07/hello-so/_test_so.c new file mode 100644 index 0000000..889e666 --- /dev/null +++ b/examples/ch2-07/hello-so/_test_so.c @@ -0,0 +1,7 @@ +#include "say-hello.h" +#include + +int main() { + SayHello("gopher"); + return 0; +} diff --git a/examples/ch2-07/hello-so/hello.py b/examples/ch2-07/hello-so/hello.py new file mode 100644 index 0000000..a5b01ec --- /dev/null +++ b/examples/ch2-07/hello-so/hello.py @@ -0,0 +1,9 @@ +from ctypes import * + +libso = CDLL("./say-hello.so") + +SayHello = libso.SayHello +SayHello.argtypes = [c_char_p] +SayHello.restype = None + +SayHello(c_char_p(b"hello")) diff --git a/examples/ch2-07/hello-so/main.go b/examples/ch2-07/hello-so/main.go new file mode 100644 index 0000000..d95e599 --- /dev/null +++ b/examples/ch2-07/hello-so/main.go @@ -0,0 +1,11 @@ +package main + +import "C" +import "fmt" + +func main() {} + +//export SayHello +func SayHello(name *C.char) { + fmt.Printf("hello %s!\n", C.GoString(name)) +} diff --git a/examples/ch2-07/hello-so/say-hello.h b/examples/ch2-07/hello-so/say-hello.h new file mode 100644 index 0000000..0446c5c --- /dev/null +++ b/examples/ch2-07/hello-so/say-hello.h @@ -0,0 +1,60 @@ +/* Created by "go tool cgo" - DO NOT EDIT. */ + +/* package command-line-arguments */ + +/* Start of preamble from import "C" comments. */ + + + + +/* End of preamble from import "C" comments. */ + + +/* Start of boilerplate cgo prologue. */ +#line 1 "cgo-gcc-export-header-prolog" + +#ifndef GO_CGO_PROLOGUE_H +#define GO_CGO_PROLOGUE_H + +typedef signed char GoInt8; +typedef unsigned char GoUint8; +typedef short GoInt16; +typedef unsigned short GoUint16; +typedef int GoInt32; +typedef unsigned int GoUint32; +typedef long long GoInt64; +typedef unsigned long long GoUint64; +typedef GoInt64 GoInt; +typedef GoUint64 GoUint; +typedef __SIZE_TYPE__ GoUintptr; +typedef float GoFloat32; +typedef double GoFloat64; +typedef float _Complex GoComplex64; +typedef double _Complex GoComplex128; + +/* + static assertion to make sure the file is being used on architecture + at least with matching size of GoInt. +*/ +typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; + +typedef struct { const char *p; GoInt n; } GoString; +typedef void *GoMap; +typedef void *GoChan; +typedef struct { void *t; void *v; } GoInterface; +typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; + +#endif + +/* End of boilerplate cgo prologue. */ + +#ifdef __cplusplus +extern "C" { +#endif + + +extern void SayHello(char* p0); + +#ifdef __cplusplus +} +#endif diff --git a/examples/ch2-xx/hello/.gitignore b/examples/ch2-xx/hello/.gitignore new file mode 100644 index 0000000..f9cccb9 --- /dev/null +++ b/examples/ch2-xx/hello/.gitignore @@ -0,0 +1 @@ +!/_obj diff --git a/examples/ch2-xx/hello/Makefile b/examples/ch2-xx/hello/Makefile new file mode 100644 index 0000000..d09055d --- /dev/null +++ b/examples/ch2-xx/hello/Makefile @@ -0,0 +1,2 @@ +default: + go tool cgo hello.go diff --git a/examples/ch2-xx/hello/_obj/_cgo_export.c b/examples/ch2-xx/hello/_obj/_cgo_export.c new file mode 100644 index 0000000..955b3be --- /dev/null +++ b/examples/ch2-xx/hello/_obj/_cgo_export.c @@ -0,0 +1,58 @@ +/* Created by cgo - DO NOT EDIT. */ +#include +#include "_cgo_export.h" + +extern void crosscall2(void (*fn)(void *, int, __SIZE_TYPE__), void *, int, __SIZE_TYPE__); +extern __SIZE_TYPE__ _cgo_wait_runtime_init_done(); +extern void _cgo_release_context(__SIZE_TYPE__); + +extern char* _cgo_topofstack(void); +#define CGO_NO_SANITIZE_THREAD +#define _cgo_tsan_acquire() +#define _cgo_tsan_release() + +extern void _cgoexp_16f1900c27a8_helloInt(void *, int, __SIZE_TYPE__); + +CGO_NO_SANITIZE_THREAD +void helloInt(GoInt p0) +{ + __SIZE_TYPE__ _cgo_ctxt = _cgo_wait_runtime_init_done(); + struct { + GoInt p0; + } __attribute__((__packed__)) a; + a.p0 = p0; + _cgo_tsan_release(); + crosscall2(_cgoexp_16f1900c27a8_helloInt, &a, 8, _cgo_ctxt); + _cgo_tsan_acquire(); + _cgo_release_context(_cgo_ctxt); +} +extern void _cgoexp_16f1900c27a8_helloString(void *, int, __SIZE_TYPE__); + +CGO_NO_SANITIZE_THREAD +void helloString(GoString p0) +{ + __SIZE_TYPE__ _cgo_ctxt = _cgo_wait_runtime_init_done(); + struct { + GoString p0; + } __attribute__((__packed__)) a; + a.p0 = p0; + _cgo_tsan_release(); + crosscall2(_cgoexp_16f1900c27a8_helloString, &a, 16, _cgo_ctxt); + _cgo_tsan_acquire(); + _cgo_release_context(_cgo_ctxt); +} +extern void _cgoexp_16f1900c27a8_helloSlice(void *, int, __SIZE_TYPE__); + +CGO_NO_SANITIZE_THREAD +void helloSlice(GoSlice p0) +{ + __SIZE_TYPE__ _cgo_ctxt = _cgo_wait_runtime_init_done(); + struct { + GoSlice p0; + } __attribute__((__packed__)) a; + a.p0 = p0; + _cgo_tsan_release(); + crosscall2(_cgoexp_16f1900c27a8_helloSlice, &a, 24, _cgo_ctxt); + _cgo_tsan_acquire(); + _cgo_release_context(_cgo_ctxt); +} diff --git a/examples/ch2-xx/hello/_obj/_cgo_export.h b/examples/ch2-xx/hello/_obj/_cgo_export.h new file mode 100644 index 0000000..b6332d9 --- /dev/null +++ b/examples/ch2-xx/hello/_obj/_cgo_export.h @@ -0,0 +1,64 @@ +/* Created by "go tool cgo" - DO NOT EDIT. */ + +/* package main */ + +/* Start of preamble from import "C" comments. */ + + + + +/* End of preamble from import "C" comments. */ + + +/* Start of boilerplate cgo prologue. */ +#line 1 "cgo-gcc-export-header-prolog" + +#ifndef GO_CGO_PROLOGUE_H +#define GO_CGO_PROLOGUE_H + +typedef signed char GoInt8; +typedef unsigned char GoUint8; +typedef short GoInt16; +typedef unsigned short GoUint16; +typedef int GoInt32; +typedef unsigned int GoUint32; +typedef long long GoInt64; +typedef unsigned long long GoUint64; +typedef GoInt64 GoInt; +typedef GoUint64 GoUint; +typedef __SIZE_TYPE__ GoUintptr; +typedef float GoFloat32; +typedef double GoFloat64; +typedef float _Complex GoComplex64; +typedef double _Complex GoComplex128; + +/* + static assertion to make sure the file is being used on architecture + at least with matching size of GoInt. +*/ +typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; + +typedef struct { const char *p; GoInt n; } GoString; +typedef void *GoMap; +typedef void *GoChan; +typedef struct { void *t; void *v; } GoInterface; +typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; + +#endif + +/* End of boilerplate cgo prologue. */ + +#ifdef __cplusplus +extern "C" { +#endif + + +extern void helloInt(GoInt p0); + +extern void helloString(GoString p0); + +extern void helloSlice(GoSlice p0); + +#ifdef __cplusplus +} +#endif diff --git a/examples/ch2-xx/hello/_obj/_cgo_flags b/examples/ch2-xx/hello/_obj/_cgo_flags new file mode 100644 index 0000000..3c91b0f --- /dev/null +++ b/examples/ch2-xx/hello/_obj/_cgo_flags @@ -0,0 +1 @@ +_CGO_CFLAGS= diff --git a/examples/ch2-xx/hello/_obj/_cgo_gotypes.go b/examples/ch2-xx/hello/_obj/_cgo_gotypes.go new file mode 100644 index 0000000..64ed703 --- /dev/null +++ b/examples/ch2-xx/hello/_obj/_cgo_gotypes.go @@ -0,0 +1,70 @@ +// Created by cgo - DO NOT EDIT + +package main + +import "unsafe" + +import _ "runtime/cgo" + +import "syscall" + +var _ syscall.Errno +func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr } + +//go:linkname _Cgo_always_false runtime.cgoAlwaysFalse +var _Cgo_always_false bool +//go:linkname _Cgo_use runtime.cgoUse +func _Cgo_use(interface{}) +type _Ctype_void [0]byte + +//go:linkname _cgo_runtime_cgocall runtime.cgocall +func _cgo_runtime_cgocall(unsafe.Pointer, uintptr) int32 + +//go:linkname _cgo_runtime_cgocallback runtime.cgocallback +func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr, uintptr) + +//go:linkname _cgoCheckPointer runtime.cgoCheckPointer +func _cgoCheckPointer(interface{}, ...interface{}) + +//go:linkname _cgoCheckResult runtime.cgoCheckResult +func _cgoCheckResult(interface{}) + +//go:cgo_export_dynamic helloInt +//go:linkname _cgoexp_16f1900c27a8_helloInt _cgoexp_16f1900c27a8_helloInt +//go:cgo_export_static _cgoexp_16f1900c27a8_helloInt +//go:nosplit +//go:norace +func _cgoexp_16f1900c27a8_helloInt(a unsafe.Pointer, n int32, ctxt uintptr) { + fn := _cgoexpwrap_16f1900c27a8_helloInt + _cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n), ctxt); +} + +func _cgoexpwrap_16f1900c27a8_helloInt(p0 int) { + helloInt(p0) +} +//go:cgo_export_dynamic helloString +//go:linkname _cgoexp_16f1900c27a8_helloString _cgoexp_16f1900c27a8_helloString +//go:cgo_export_static _cgoexp_16f1900c27a8_helloString +//go:nosplit +//go:norace +func _cgoexp_16f1900c27a8_helloString(a unsafe.Pointer, n int32, ctxt uintptr) { + fn := _cgoexpwrap_16f1900c27a8_helloString + _cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n), ctxt); +} + +func _cgoexpwrap_16f1900c27a8_helloString(p0 string) { + helloString(p0) +} +//go:cgo_export_dynamic helloSlice +//go:linkname _cgoexp_16f1900c27a8_helloSlice _cgoexp_16f1900c27a8_helloSlice +//go:cgo_export_static _cgoexp_16f1900c27a8_helloSlice +//go:nosplit +//go:norace +func _cgoexp_16f1900c27a8_helloSlice(a unsafe.Pointer, n int32, ctxt uintptr) { + fn := _cgoexpwrap_16f1900c27a8_helloSlice + _cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n), ctxt); +} + +func _cgoexpwrap_16f1900c27a8_helloSlice(p0 []byte) { + helloSlice(p0) +} diff --git a/examples/ch2-xx/hello/_obj/_cgo_main.c b/examples/ch2-xx/hello/_obj/_cgo_main.c new file mode 100644 index 0000000..f0ae18c --- /dev/null +++ b/examples/ch2-xx/hello/_obj/_cgo_main.c @@ -0,0 +1,12 @@ +int main() { return 0; } +void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt) { } +__SIZE_TYPE__ _cgo_wait_runtime_init_done() { return 0; } +void _cgo_release_context(__SIZE_TYPE__ ctxt) { } +char* _cgo_topofstack(void) { return (char*)0; } +void _cgo_allocate(void *a, int c) { } +void _cgo_panic(void *a, int c) { } +void _cgo_reginit(void) { } +#line 1 "cgo-generated-wrappers" +int _cgoexp_16f1900c27a8_helloInt; +int _cgoexp_16f1900c27a8_helloString; +int _cgoexp_16f1900c27a8_helloSlice; diff --git a/examples/ch2-xx/hello/_obj/hello.cgo1.go b/examples/ch2-xx/hello/_obj/hello.cgo1.go new file mode 100644 index 0000000..d70d524 --- /dev/null +++ b/examples/ch2-xx/hello/_obj/hello.cgo1.go @@ -0,0 +1,24 @@ +// Created by cgo - DO NOT EDIT + +//line /Users/chai/go/src/github.com/chai2010/advanced-go-programming-book/examples/ch2-xx/hello/hello.go:1 +package main + +//line /Users/chai/go/src/github.com/chai2010/advanced-go-programming-book/examples/ch2-xx/hello/hello.go:5 +func main() { + helloString("hello") +} + +//line /Users/chai/go/src/github.com/chai2010/advanced-go-programming-book/examples/ch2-xx/hello/hello.go:10 +func helloInt(s int) { + println(s) +} + +//line /Users/chai/go/src/github.com/chai2010/advanced-go-programming-book/examples/ch2-xx/hello/hello.go:15 +func helloString(s string) { + println(s) +} + +//line /Users/chai/go/src/github.com/chai2010/advanced-go-programming-book/examples/ch2-xx/hello/hello.go:20 +func helloSlice(s []byte) { + println(string(s)) +} diff --git a/examples/ch2-xx/hello/_obj/hello.cgo2.c b/examples/ch2-xx/hello/_obj/hello.cgo2.c new file mode 100644 index 0000000..0196be1 --- /dev/null +++ b/examples/ch2-xx/hello/_obj/hello.cgo2.c @@ -0,0 +1,31 @@ + + +#line 1 "cgo-gcc-prolog" +/* + If x and y are not equal, the type will be invalid + (have a negative array count) and an inscrutable error will come + out of the compiler and hopefully mention "name". +*/ +#define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1]; + +/* Check at compile time that the sizes we use match our expectations. */ +#define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n) + +__cgo_size_assert(char, 1) +__cgo_size_assert(short, 2) +__cgo_size_assert(int, 4) +typedef long long __cgo_long_long; +__cgo_size_assert(__cgo_long_long, 8) +__cgo_size_assert(float, 4) +__cgo_size_assert(double, 8) + +extern char* _cgo_topofstack(void); + +#include +#include + + +#define CGO_NO_SANITIZE_THREAD +#define _cgo_tsan_acquire() +#define _cgo_tsan_release() + diff --git a/examples/ch2-xx/hello/hello.go b/examples/ch2-xx/hello/hello.go new file mode 100644 index 0000000..0c93fcf --- /dev/null +++ b/examples/ch2-xx/hello/hello.go @@ -0,0 +1,22 @@ +package main + +import "C" + +func main() { + helloString("hello") // _GoString_ +} + +//export helloInt +func helloInt(s int) { + println(s) +} + +//export helloString +func helloString(s string) { + println(s) +} + +//export helloSlice +func helloSlice(s []byte) { + println(string(s)) +}