Skip to content

Instantly share code, notes, and snippets.

@wangkuiyi
Created February 23, 2013 13:40
Show Gist options
  • Save wangkuiyi/5019792 to your computer and use it in GitHub Desktop.
Save wangkuiyi/5019792 to your computer and use it in GitHub Desktop.
Go invokes C samples
cc_plugin(
name = 'lda',
srcs = ['lda.c'],
deps = ['#pthread']
)
#include "lda.h"
#include <stdlib.h>
#include <stdint.h>
OrderedSparseHistogram newHist(int dim) {
OrderedSparseHistogram h;
h.topics.array = malloc(sizeof(int32_t) * dim);
h.topics.len = dim;
h.topics.cap = dim;
h.counts.array = malloc(sizeof(int64_t) * dim);
h.counts.len = dim;
h.counts.cap = dim;
return h;
}
OrderedSparseHistogram Sample(Document* d) {
uint32_t i = 0;
Word* words = (Word*)(d->words.array);
for (i = 0; i < d->words.len; ++i) {
words[i].topic = 111;
}
OrderedSparseHistogram h = newHist(10);
int32_t* topics = (int32_t*)(h.topics.array);
int64_t* counts = (int64_t*)(h.counts.array);
for (i = 0; i < h.topics.len; ++i) {
topics[i] = i;
counts[i] = i*10;
}
return h;
}
void FreeHist(OrderedSparseHistogram h) {
free(h.topics.array);
free(h.counts.array);
}
package main
/*
#cgo darwin CFLAGS: -I.
#cgo darwin LDFLAGS: -L../../build64_release/src/learn-cgo/c -llda
#include "c/lda.h"
*/
import "C"
import (
"fmt"
"unsafe"
)
type Word struct {
word int32
topic int32
}
type OrderedSparseHistogram struct {
topics []int32
counts []int64
}
type Document struct {
words []Word
hist OrderedSparseHistogram
}
func CopyCHist(h C.OrderedSparseHistogram) OrderedSparseHistogram {
r := OrderedSparseHistogram {
topics: make([]int32, h.topics.len),
counts: make([]int64, h.topics.len)}
copy(r.topics, *(*[]int32)(unsafe.Pointer(&h.topics)))
copy(r.counts, *(*[]int64)(unsafe.Pointer(&h.counts)))
return r
}
func main() {
d := Document{
words: []Word{ {word:0, topic:0}, {word:1, topic:1}, {word:2, topic:2} },
hist: OrderedSparseHistogram{
topics: []int32{1,2,3},
counts: []int64{9,9,9}}}
fmt.Println(d)
h := C.Sample((*C.Document)(unsafe.Pointer(&d)))
d.hist = CopyCHist(h)
C.FreeHist(h)
fmt.Println(d)
}
#ifndef LEARN_CGO_C_LDA_H_
#define LEARN_CGO_C_LDA_H_
#include <stdint.h>
typedef struct {
int32_t word;
int32_t topic;
} Word;
typedef struct {
void* array;
uint32_t len;
uint32_t cap;
} Slice;
typedef struct {
Slice topics;
Slice counts;
} OrderedSparseHistogram;
typedef struct {
Slice words;
OrderedSparseHistogram hist;
} Document;
OrderedSparseHistogram Sample(Document*);
void FreeHist(OrderedSparseHistogram);
#endif // LEARN_CGO_C_LDA_H_
@fandywang
Copy link

有个改进点:

C代码Sample中不做newHist调用,是否申请新的内存交由C++决定,如果go申请的内存足够大,C\C++直接复用即可。

lda.go 中可以先保存 d.hist.topics.array和d.hist.counts.array首地址(分别为p1和p2),在go调用C(h := C.Sample((*C.Document)(unsafe.Pointer(&d))))后,判断h.topics.array和h.counts.array与p1、p2是否相等,如果相等,说明C++并未修改go申请的内存(即使有写操作,也只是在go申请内存上做的值修改),此时,不需要lda.go L48~L49的copy和free操作了,而且这时就是我们想要的三种语言共享内存的效果,可以进一步提高效率。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment