From cbe21e4cbc1a0ef1a0a5e46beacefb0337822c70 Mon Sep 17 00:00:00 2001 From: chai2010 Date: Fri, 5 Jan 2018 22:14:23 +0800 Subject: [PATCH] =?UTF-8?q?ch2-05:=20=E5=A2=9E=E5=8A=A0Go=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=E5=88=B0C++=E5=AF=B9=E8=B1=A1=E4=BE=8B=E5=AD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/ch2-05/class-go2cc/goobj.go | 53 ++++++++++++++++++++++ examples/ch2-05/class-go2cc/main.cc | 14 ++++++ examples/ch2-05/class-go2cc/main.go | 9 ++++ examples/ch2-05/class-go2cc/persion.go | 22 +++++++++ examples/ch2-05/class-go2cc/person.cc | 1 + examples/ch2-05/class-go2cc/person.h | 23 ++++++++++ examples/ch2-05/class-go2cc/person_capi.go | 42 +++++++++++++++++ examples/ch2-05/class-go2cc/person_capi.h | 10 ++++ 8 files changed, 174 insertions(+) create mode 100644 examples/ch2-05/class-go2cc/goobj.go create mode 100644 examples/ch2-05/class-go2cc/main.cc create mode 100644 examples/ch2-05/class-go2cc/main.go create mode 100644 examples/ch2-05/class-go2cc/persion.go create mode 100644 examples/ch2-05/class-go2cc/person.cc create mode 100644 examples/ch2-05/class-go2cc/person.h create mode 100644 examples/ch2-05/class-go2cc/person_capi.go create mode 100644 examples/ch2-05/class-go2cc/person_capi.h diff --git a/examples/ch2-05/class-go2cc/goobj.go b/examples/ch2-05/class-go2cc/goobj.go new file mode 100644 index 0000000..a256c71 --- /dev/null +++ b/examples/ch2-05/class-go2cc/goobj.go @@ -0,0 +1,53 @@ +package main + +import ( + "sync" +) + +type ObjectId int32 + +var refs struct { + sync.Mutex + objs map[ObjectId]interface{} + next ObjectId +} + +func init() { + refs.Lock() + defer refs.Unlock() + + refs.objs = make(map[ObjectId]interface{}) + refs.next = 1000 +} + +func NewObjectId(obj interface{}) ObjectId { + refs.Lock() + defer refs.Unlock() + + id := refs.next + refs.next++ + + refs.objs[id] = obj + return id +} + +func (id ObjectId) IsNil() bool { + return id == 0 +} + +func (id ObjectId) Get() interface{} { + refs.Lock() + defer refs.Unlock() + + return refs.objs[id] +} + +func (id ObjectId) Free() interface{} { + refs.Lock() + defer refs.Unlock() + + obj := refs.objs[id] + delete(refs.objs, id) + + return obj +} diff --git a/examples/ch2-05/class-go2cc/main.cc b/examples/ch2-05/class-go2cc/main.cc new file mode 100644 index 0000000..fd55376 --- /dev/null +++ b/examples/ch2-05/class-go2cc/main.cc @@ -0,0 +1,14 @@ +#include "person.h" + +#include + +extern "C" void Main() { + auto p = Person::New("gopher", 10); + + char buf[64]; + char* name = p->GetName(buf, sizeof(buf)-1); + int age = p->GetAge(); + + printf("%s, %d years old.\n", name, age); + p->Delete(); +} diff --git a/examples/ch2-05/class-go2cc/main.go b/examples/ch2-05/class-go2cc/main.go new file mode 100644 index 0000000..8525d8f --- /dev/null +++ b/examples/ch2-05/class-go2cc/main.go @@ -0,0 +1,9 @@ +package main + +// #cgo CXXFLAGS: -std=c++11 +// extern void Main(); +import "C" + +func main() { + C.Main() +} diff --git a/examples/ch2-05/class-go2cc/persion.go b/examples/ch2-05/class-go2cc/persion.go new file mode 100644 index 0000000..b11b353 --- /dev/null +++ b/examples/ch2-05/class-go2cc/persion.go @@ -0,0 +1,22 @@ +package main + +type Person struct { + name string + age int +} + +func NewPerson(name string, age int) *Person { + return &Person{ + name: name, + age: age, + } +} + +func (p *Person) Set(name string, age int) { + p.name = name + p.age = age +} + +func (p *Person) Get() (name string, age int) { + return p.name, p.age +} diff --git a/examples/ch2-05/class-go2cc/person.cc b/examples/ch2-05/class-go2cc/person.cc new file mode 100644 index 0000000..d59cf55 --- /dev/null +++ b/examples/ch2-05/class-go2cc/person.cc @@ -0,0 +1 @@ +#include "person.h" diff --git a/examples/ch2-05/class-go2cc/person.h b/examples/ch2-05/class-go2cc/person.h new file mode 100644 index 0000000..f5f6b7e --- /dev/null +++ b/examples/ch2-05/class-go2cc/person.h @@ -0,0 +1,23 @@ + +extern "C" { + #include "./person_capi.h" +} + +struct Person { + static Person* New(const char* name, int age) { + return (Person*)person_new((char*)name, age); + } + void Delete() { + person_delete(person_handle_t(this)); + } + + void Set(char* name, int age) { + person_set(person_handle_t(this), name, age); + } + char* GetName(char* buf, int size) { + return person_get_name(person_handle_t(this), buf, size); + } + int GetAge() { + return person_get_age(person_handle_t(this)); + } +}; diff --git a/examples/ch2-05/class-go2cc/person_capi.go b/examples/ch2-05/class-go2cc/person_capi.go new file mode 100644 index 0000000..a072f72 --- /dev/null +++ b/examples/ch2-05/class-go2cc/person_capi.go @@ -0,0 +1,42 @@ +package main + +//#include "./person_capi.h" +import "C" +import "unsafe" + +//export person_new +func person_new(name *C.char, age C.int) C.person_handle_t { + id := NewObjectId(NewPerson(C.GoString(name), int(age))) + return C.person_handle_t(id) +} + +//export person_delete +func person_delete(h C.person_handle_t) { + ObjectId(h).Free() +} + +//export person_set +func person_set(h C.person_handle_t, name *C.char, age C.int) { + p := ObjectId(h).Get().(*Person) + p.Set(C.GoString(name), int(age)) +} + +//export person_get_name +func person_get_name(h C.person_handle_t, buf *C.char, size C.int) *C.char { + p := ObjectId(h).Get().(*Person) + name, _ := p.Get() + + n := int(size) - 1 + bufSlice := ((*[1 << 31]byte)(unsafe.Pointer(buf)))[0:n:n] + n = copy(bufSlice, []byte(name)) + bufSlice[n] = 0 + + return buf +} + +//export person_get_age +func person_get_age(h C.person_handle_t) C.int { + p := ObjectId(h).Get().(*Person) + _, age := p.Get() + return C.int(age) +} diff --git a/examples/ch2-05/class-go2cc/person_capi.h b/examples/ch2-05/class-go2cc/person_capi.h new file mode 100644 index 0000000..698fca1 --- /dev/null +++ b/examples/ch2-05/class-go2cc/person_capi.h @@ -0,0 +1,10 @@ +#include + +typedef uintptr_t person_handle_t; + +person_handle_t person_new(char* name, int age); +void person_delete(person_handle_t p); + +void person_set(person_handle_t p, char* name, int age); +char* person_get_name(person_handle_t p, char* buf, int size); +int person_get_age(person_handle_t p);