mirror of
https://github.com/chai2010/advanced-go-programming-book.git
synced 2025-05-24 04:22:22 +00:00
ch2-6: 提炼 qsort 例子
This commit is contained in:
parent
ffa45e65ca
commit
84718a8e50
@ -6,14 +6,22 @@ package main
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
|
||||
static int compare(const void* a, const void* b) {
|
||||
typedef int (*qsort_cmp_func_t)(const void* a, const void* b);
|
||||
|
||||
// disable static
|
||||
int qsort_compare_callback(const void* a, const void* b) {
|
||||
const int* pa = (int*)a;
|
||||
const int* pb = (int*)b;
|
||||
return *pa - *pb;
|
||||
}
|
||||
|
||||
static void qsort_proxy(int* values, size_t len, size_t elemsize) {
|
||||
qsort(values, len, sizeof(values[0]), compare);
|
||||
static int compare(const void* a, const void* b) {
|
||||
const int* pa = (int*)a;
|
||||
const int* pb = (int*)b;
|
||||
return *pa - *pb;
|
||||
}
|
||||
static qsort_cmp_func_t get_compare_ptr() {
|
||||
return compare;
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
@ -21,14 +29,24 @@ import "C"
|
||||
import "unsafe"
|
||||
import "fmt"
|
||||
|
||||
func qsort(base unsafe.Pointer, num, size C.size_t, cmp C.qsort_cmp_func_t) {
|
||||
C.qsort(base, num, size, C.qsort_cmp_func_t(cmp))
|
||||
}
|
||||
|
||||
func main() {
|
||||
values := []int32{42, 9, 101, 95, 27, 25}
|
||||
|
||||
C.qsort_proxy(
|
||||
(*C.int)(unsafe.Pointer(&values[0])),
|
||||
C.size_t(len(values)),
|
||||
C.size_t(unsafe.Sizeof(values[0])),
|
||||
qsort(unsafe.Pointer(&values[0]),
|
||||
C.size_t(len(values)), C.size_t(unsafe.Sizeof(values[0])),
|
||||
C.get_compare_ptr(), // static callback must use proxy get
|
||||
)
|
||||
fmt.Println(values)
|
||||
|
||||
values = []int32{42, 9, 101, 95, 27, 25}
|
||||
|
||||
qsort(unsafe.Pointer(&values[0]),
|
||||
C.size_t(len(values)), C.size_t(unsafe.Sizeof(values[0])),
|
||||
C.qsort_cmp_func_t(unsafe.Pointer(C.qsort_compare_callback)),
|
||||
)
|
||||
fmt.Println(values)
|
||||
}
|
||||
|
@ -9,14 +9,6 @@ package main
|
||||
typedef int (*qsort_cmp_func_t)(const void* a, const void* b);
|
||||
|
||||
extern int go_qsort_compare(void* a, void* b);
|
||||
|
||||
static int compare(const void* a, const void* b) {
|
||||
return go_qsort_compare((void*)(a), (void*)(b));
|
||||
}
|
||||
|
||||
static qsort_cmp_func_t get_compare_ptr() {
|
||||
return compare;
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
@ -24,20 +16,24 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func main() {
|
||||
values := []int32{42, 9, 101, 95, 27, 25}
|
||||
|
||||
C.qsort(unsafe.Pointer(&values[0]),
|
||||
C.size_t(len(values)), C.size_t(unsafe.Sizeof(values[0])),
|
||||
C.get_compare_ptr(),
|
||||
)
|
||||
|
||||
fmt.Println(values)
|
||||
}
|
||||
|
||||
//export go_qsort_compare
|
||||
func go_qsort_compare(a, b unsafe.Pointer) C.int {
|
||||
pa := (*C.int)(a)
|
||||
pb := (*C.int)(b)
|
||||
return C.int(*pa - *pb)
|
||||
}
|
||||
|
||||
func qsort(base unsafe.Pointer, num, size C.size_t, cmp C.qsort_cmp_func_t) {
|
||||
C.qsort(base, num, size, C.qsort_cmp_func_t(cmp))
|
||||
}
|
||||
|
||||
func main() {
|
||||
values := []int32{42, 9, 101, 95, 27, 25}
|
||||
|
||||
qsort(unsafe.Pointer(&values[0]),
|
||||
C.size_t(len(values)), C.size_t(unsafe.Sizeof(values[0])),
|
||||
C.qsort_cmp_func_t(unsafe.Pointer(C.go_qsort_compare)),
|
||||
)
|
||||
|
||||
fmt.Println(values)
|
||||
}
|
||||
|
@ -3,6 +3,10 @@
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
|
||||
@ -11,25 +15,40 @@ extern int go_qsort_compare(void* a, void* b);
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func main() {
|
||||
values := []int32{42, 9, 101, 95, 27, 25}
|
||||
|
||||
C.qsort(unsafe.Pointer(&values[0]),
|
||||
C.size_t(len(values)), C.size_t(unsafe.Sizeof(values[0])),
|
||||
(C.qsort_cmp_func_t)(unsafe.Pointer(C.go_qsort_compare)),
|
||||
)
|
||||
|
||||
fmt.Println(values)
|
||||
var go_qsort_compare_info struct {
|
||||
fn func(a, b unsafe.Pointer) int
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
//export go_qsort_compare
|
||||
func go_qsort_compare(a, b unsafe.Pointer) C.int {
|
||||
pa := (*C.int)(a)
|
||||
pb := (*C.int)(b)
|
||||
|
||||
return C.int(*pa - *pb)
|
||||
return C.int(go_qsort_compare_info.fn(a, b))
|
||||
}
|
||||
|
||||
func qsort(base unsafe.Pointer, num, size int, cmp func(a, b unsafe.Pointer) int) {
|
||||
go_qsort_compare_info.Lock()
|
||||
defer go_qsort_compare_info.Unlock()
|
||||
|
||||
go_qsort_compare_info.fn = cmp
|
||||
|
||||
C.qsort(base, C.size_t(num), C.size_t(size),
|
||||
C.qsort_cmp_func_t(C.go_qsort_compare),
|
||||
)
|
||||
}
|
||||
|
||||
func main() {
|
||||
values := []int32{42, 9, 101, 95, 27, 25}
|
||||
|
||||
qsort(unsafe.Pointer(&values[0]), len(values), int(unsafe.Sizeof(values[0])),
|
||||
func(a, b unsafe.Pointer) int {
|
||||
pa, pb := (*C.int)(a), (*C.int)(b)
|
||||
return int(*pa - *pb)
|
||||
},
|
||||
)
|
||||
|
||||
fmt.Println(values)
|
||||
}
|
||||
|
@ -3,48 +3,85 @@
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef int (*qsort_cmp_func_t)(const void* a, const void* b);
|
||||
|
||||
extern int go_qsort_compare(void* a, void* b);
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func main() {
|
||||
values := []int32{42, 9, 101, 95, 27, 25}
|
||||
var go_qsort_compare_info struct {
|
||||
slice interface{}
|
||||
base uintptr
|
||||
elemsize uintptr
|
||||
fn func(a, b int) int
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
go_qsort_compare_info.Lock()
|
||||
defer go_qsort_compare_info.Unlock()
|
||||
|
||||
go_qsort_compare_info.fn = func(a, b unsafe.Pointer) C.int {
|
||||
pa := (*C.int)(a)
|
||||
pb := (*C.int)(b)
|
||||
return C.int(*pa - *pb)
|
||||
}
|
||||
|
||||
C.qsort(unsafe.Pointer(&values[0]),
|
||||
C.size_t(len(values)), C.size_t(unsafe.Sizeof(values[0])),
|
||||
(C.qsort_cmp_func_t)(unsafe.Pointer(C.go_qsort_compare)),
|
||||
)
|
||||
|
||||
fmt.Println(values)
|
||||
//export go_qsort_compare_save_base
|
||||
func go_qsort_compare_save_base(base unsafe.Pointer) {
|
||||
go_qsort_compare_info.base = uintptr(base)
|
||||
}
|
||||
|
||||
//export go_qsort_compare
|
||||
func go_qsort_compare(a, b unsafe.Pointer) C.int {
|
||||
return go_qsort_compare_info.fn(a, b)
|
||||
if go_qsort_compare_info.base == 0 {
|
||||
sv := reflect.ValueOf(go_qsort_compare_info.slice)
|
||||
go_qsort_compare_info.base = uintptr(unsafe.Pointer(sv.Index(0).Addr().Pointer()))
|
||||
}
|
||||
|
||||
var (
|
||||
// array memory is locked
|
||||
base = go_qsort_compare_info.base
|
||||
elemsize = go_qsort_compare_info.elemsize
|
||||
)
|
||||
|
||||
i := int((uintptr(a) - base) / elemsize)
|
||||
j := int((uintptr(b) - base) / elemsize)
|
||||
|
||||
return C.int(go_qsort_compare_info.fn(i, j))
|
||||
}
|
||||
|
||||
var go_qsort_compare_info struct {
|
||||
fn func(a, b unsafe.Pointer) C.int
|
||||
sync.RWMutex
|
||||
func qsort(slice interface{}, fn func(a, b int) int) {
|
||||
sv := reflect.ValueOf(slice)
|
||||
if sv.Kind() != reflect.Slice {
|
||||
panic(fmt.Sprintf("qsort called with non-slice value of type %T", slice))
|
||||
}
|
||||
if sv.Len() == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
go_qsort_compare_info.Lock()
|
||||
defer go_qsort_compare_info.Unlock()
|
||||
|
||||
// baseMem = unsafe.Pointer(sv.Index(0).Addr().Pointer())
|
||||
// baseMem maybe moved, so must saved after call C.fn
|
||||
go_qsort_compare_info.slice = slice
|
||||
go_qsort_compare_info.elemsize = sv.Type().Elem().Size()
|
||||
go_qsort_compare_info.fn = fn
|
||||
|
||||
C.qsort(
|
||||
unsafe.Pointer(sv.Index(0).Addr().Pointer()),
|
||||
C.size_t(sv.Len()), C.size_t(sv.Type().Elem().Size()),
|
||||
C.qsort_cmp_func_t(C.go_qsort_compare),
|
||||
)
|
||||
}
|
||||
|
||||
func main() {
|
||||
values := []int64{42, 9, 101, 95, 27, 25}
|
||||
|
||||
qsort(values, func(i, j int) int {
|
||||
return int(values[i] - values[j])
|
||||
})
|
||||
|
||||
fmt.Println(values)
|
||||
}
|
||||
|
@ -1,56 +0,0 @@
|
||||
// Copyright © 2018 ChaiShushan <chaishushan{AT}gmail.com>.
|
||||
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef int (*qsort_cmp_func_t)(const void* a, const void* b);
|
||||
extern int go_qsort_compare(void* a, void* b);
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func main() {
|
||||
values := []int32{42, 9, 101, 95, 27, 25}
|
||||
|
||||
qsort(values, func(a, b unsafe.Pointer) C.int {
|
||||
pa := (*C.int)(a)
|
||||
pb := (*C.int)(b)
|
||||
return C.int(*pa - *pb)
|
||||
})
|
||||
|
||||
fmt.Println(values)
|
||||
}
|
||||
|
||||
func qsort(values []int32, fn func(a, b unsafe.Pointer) C.int) {
|
||||
go_qsort_compare_info.Lock()
|
||||
defer go_qsort_compare_info.Unlock()
|
||||
|
||||
go_qsort_compare_info.fn = fn
|
||||
|
||||
C.qsort(
|
||||
unsafe.Pointer(&values[0]),
|
||||
C.size_t(len(values)),
|
||||
C.size_t(unsafe.Sizeof(values[0])),
|
||||
(C.qsort_cmp_func_t)(unsafe.Pointer(C.go_qsort_compare)),
|
||||
)
|
||||
}
|
||||
|
||||
//export go_qsort_compare
|
||||
func go_qsort_compare(a, b unsafe.Pointer) C.int {
|
||||
return go_qsort_compare_info.fn(a, b)
|
||||
}
|
||||
|
||||
var go_qsort_compare_info struct {
|
||||
fn func(a, b unsafe.Pointer) C.int
|
||||
sync.RWMutex
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
// Copyright © 2018 ChaiShushan <chaishushan{AT}gmail.com>.
|
||||
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
|
||||
package main
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef int (*qsort_cmp_func_t)(const void* a, const void* b);
|
||||
|
||||
extern int go_qsort_compare(void* a, void* b);
|
||||
extern void go_qsort_compare_save_base(void* base);
|
||||
|
||||
static void
|
||||
qsort_proxy(
|
||||
void* base, size_t num, size_t size,
|
||||
int (*compare)(const void* a, const void* b)
|
||||
) {
|
||||
go_qsort_compare_save_base(base);
|
||||
qsort(base, num, size, compare);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func main() {
|
||||
values := []int64{42, 9, 101, 95, 27, 25}
|
||||
|
||||
fmt.Println(values)
|
||||
defer fmt.Println(values)
|
||||
|
||||
qsort(values, func(i, j int) int {
|
||||
return int(values[i] - values[j])
|
||||
})
|
||||
}
|
||||
|
||||
func qsort(slice interface{}, fn func(a, b int) int) {
|
||||
sv := reflect.ValueOf(slice)
|
||||
if sv.Kind() != reflect.Slice {
|
||||
panic(fmt.Sprintf("qsort called with non-slice value of type %T", slice))
|
||||
}
|
||||
if sv.Len() == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
go_qsort_compare_info.Lock()
|
||||
defer go_qsort_compare_info.Unlock()
|
||||
|
||||
// baseMem = unsafe.Pointer(sv.Index(0).Addr().Pointer())
|
||||
// baseMem maybe moved, so must saved after call C.fn
|
||||
go_qsort_compare_info.elemsize = sv.Type().Elem().Size()
|
||||
go_qsort_compare_info.fn = fn
|
||||
|
||||
C.qsort_proxy(
|
||||
unsafe.Pointer(unsafe.Pointer(sv.Index(0).Addr().Pointer())),
|
||||
C.size_t(sv.Len()),
|
||||
C.size_t(sv.Type().Elem().Size()),
|
||||
(C.qsort_cmp_func_t)(unsafe.Pointer(C.go_qsort_compare)),
|
||||
)
|
||||
}
|
||||
|
||||
//export go_qsort_compare
|
||||
func go_qsort_compare(a, b unsafe.Pointer) C.int {
|
||||
var (
|
||||
// array memory is locked
|
||||
base = go_qsort_compare_info.base
|
||||
elemsize = go_qsort_compare_info.elemsize
|
||||
)
|
||||
|
||||
i := int((uintptr(a) - base) / elemsize)
|
||||
j := int((uintptr(b) - base) / elemsize)
|
||||
|
||||
return C.int(go_qsort_compare_info.fn(i, j))
|
||||
}
|
||||
|
||||
//export go_qsort_compare_save_base
|
||||
func go_qsort_compare_save_base(base unsafe.Pointer) {
|
||||
go_qsort_compare_info.base = uintptr(base)
|
||||
}
|
||||
|
||||
var go_qsort_compare_info struct {
|
||||
base uintptr
|
||||
elemsize uintptr
|
||||
fn func(a, b int) int
|
||||
sync.RWMutex
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user