From e86ee4b9dd210d9bbb5ffd190fb03531fcdcce9a Mon Sep 17 00:00:00 2001 From: codingcrush Date: Sat, 27 Jul 2019 07:21:42 +0800 Subject: [PATCH] add a golang demo of so lib --- docs/api_userguide.md | 8 +- time_series_detector/demo/golang/handler.go | 95 +++++++++++++++++++ .../demo/golang/handler_test.go | 54 +++++++++++ time_series_detector/demo/golang/wrapper.h | 85 +++++++++++++++++ 4 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 time_series_detector/demo/golang/handler.go create mode 100644 time_series_detector/demo/golang/handler_test.go create mode 100644 time_series_detector/demo/golang/wrapper.h diff --git a/docs/api_userguide.md b/docs/api_userguide.md index 9684ebe..41d9aa9 100644 --- a/docs/api_userguide.md +++ b/docs/api_userguide.md @@ -531,4 +531,10 @@ prob |---|---|---| | ret | int | 返回码。0:成功;非0:失败 | | result | c_int | 检测结果是否异常。0:异常;1:正常 | -| prob | c_float | 概率值,值越小,判定为异常的置信度越高 | \ No newline at end of file +| prob | c_float | 概率值,值越小,判定为异常的置信度越高 | + +#### Go代码中调用: + +在Go中调用检测函数,需要先加载so文件,编写helper函数,再通过cgo调用; +详细demo见 `time_series_detector/demo/golang`目录 + diff --git a/time_series_detector/demo/golang/handler.go b/time_series_detector/demo/golang/handler.go new file mode 100644 index 0000000..8f481c8 --- /dev/null +++ b/time_series_detector/demo/golang/handler.go @@ -0,0 +1,95 @@ +package detector + +/* +#include +#include +#cgo CFLAGS: -I. +#cgo LDFLAGS: -ldl +*/ +import "C" + +import ( + "unsafe" +) + +const LibPath = "../../lib/libdetect.so" +const xgbModelPath = "../../model/xgb_default_model" +const xgbThreshold = 0.15 + +var mPtr unsafe.Pointer + +func init() { + hd := C.dlopen(C.CString(LibPath), C.RTLD_LAZY) + if hd == nil { + panic("dlopen failure") + } + loadModel := C.dlsym(hd, C.CString("load_model")) + valuePredict := C.dlsym(hd, C.CString("value_predict")) + ratePredict := C.dlsym(hd, C.CString("rate_predict")) + if loadModel == nil || valuePredict == nil || ratePredict == nil { + panic("dlsym failure") + } + C.setLoadModel(loadModel) + C.setValuePredict(valuePredict) + C.setRatePredict(ratePredict) + + ptr := C.callLoadModel(C.CString(xgbModelPath)) + if ptr == nil { + panic("load_model return NULL") + } + mPtr = ptr +} + +func ValueDetect(sample Sample) (bool, float64) { + dataC := make([]C.int, len(sample.DataC)) + for index, value := range sample.DataC { + dataC[index] = C.int(value) + } + dataB := make([]C.int, len(sample.DataB)) + for index, value := range sample.DataB { + dataB[index] = C.int(value) + } + dataA := make([]C.int, len(sample.DataA)) + for index, value := range sample.DataA { + dataA[index] = C.int(value) + } + prob := float64(C.callValuePredict(mPtr, + (*C.int)(unsafe.Pointer(&dataA[0])), + (*C.int)(unsafe.Pointer(&dataB[0])), + (*C.int)(unsafe.Pointer(&dataC[0])), + (C.int)(len(dataA)), + (C.int)(len(dataB)), + (C.int)(len(dataC)), + )) + return prob >= xgbThreshold, prob +} + +func RateDetect(sample Sample) (bool, float64) { + dataC := make([]C.double, len(sample.DataC)) + for index, value := range sample.DataC { + dataC[index] = C.double(value) + } + dataB := make([]C.double, len(sample.DataB)) + for index, value := range sample.DataB { + dataB[index] = C.double(value) + } + dataA := make([]C.double, len(sample.DataA)) + for index, value := range sample.DataA { + dataA[index] = C.double(value) + } + prob := float64(C.callRatePredict( + (*C.double)(unsafe.Pointer(&dataA[0])), + (*C.double)(unsafe.Pointer(&dataB[0])), + (*C.double)(unsafe.Pointer(&dataC[0])), + (C.int)(len(dataA)), + (C.int)(len(dataB)), + (C.int)(len(dataC)), + )) + return prob > 0, prob +} + +type Sample struct { + DataA []float64 + DataB []float64 + DataC []float64 +} diff --git a/time_series_detector/demo/golang/handler_test.go b/time_series_detector/demo/golang/handler_test.go new file mode 100644 index 0000000..fac3dab --- /dev/null +++ b/time_series_detector/demo/golang/handler_test.go @@ -0,0 +1,54 @@ +package detector + +import ( + _ "net/http/pprof" + "testing" +) + +func TestValueDetect(t *testing.T) { + DataC := make([]float64, 361) + for index := range DataC { + DataC[index] = 1 + } + DataB := DataC + + DataA := make([]float64, 180) + for index := range DataA { + DataA[index] = 1 + } + DataA = append(DataA, 10) + + isOk, prob := ValueDetect(Sample{ + DataA: DataA, + DataB: DataB, + DataC: DataC, + }) + t.Logf("value detect prob:%f", prob) + if isOk || prob == 1 || prob < 0 { + t.Fail() + } +} + +func TestRateDetect(t *testing.T) { + DataC := make([]float64, 361) + for index := range DataC { + DataC[index] = 1 + } + DataB := DataC + + DataA := make([]float64, 180) + for index := range DataA { + DataA[index] = 1 + } + DataA = append(DataA, 10) + + isOk, prob := RateDetect(Sample{ + DataA: DataA, + DataB: DataB, + DataC: DataC, + }) + t.Logf("rate detect prob:%f", prob) + if isOk || prob != 0 { + t.Fail() + } +} diff --git a/time_series_detector/demo/golang/wrapper.h b/time_series_detector/demo/golang/wrapper.h new file mode 100644 index 0000000..b159869 --- /dev/null +++ b/time_series_detector/demo/golang/wrapper.h @@ -0,0 +1,85 @@ +#include +#include +#include + + +typedef struct { + int* data_a; + int* data_b; + int* data_c; + int len_a; + int len_b; + int len_c; +} ValueData; + +typedef struct { + double* data_a; + double* data_b; + double* data_c; + int len_a; + int len_b; + int len_c; +} RateData; + +void * (*load_model)(const char*); +void setLoadModel(void* fn) { + load_model = fn; +} +void * callLoadModel(const char *fname){ + return load_model(fname); +}; + +int (*value_predict)(void *, ValueData*, int*, float*); +void setValuePredict(void* fn){ + value_predict = fn; +} +float callValuePredict(void * mhandle, int* data_a, int* data_b, int* data_c, int len_a, int len_b, int len_c){ + int sample_result=0; + float prob=0; + + ValueData *dt=malloc(sizeof(ValueData)); + dt->data_a = (int*)malloc(sizeof(int)*len_a); + dt->data_b = (int*)malloc(sizeof(int)*len_b); + dt->data_c = (int*)malloc(sizeof(int)*len_c); + memcpy(dt->data_a, data_a, sizeof(int)*len_a); + memcpy(dt->data_b, data_b, sizeof(int)*len_b); + memcpy(dt->data_c, data_c, sizeof(int)*len_c); + dt->len_a = len_a; + dt->len_b = len_b; + dt->len_c = len_c; + + value_predict(mhandle, dt, &sample_result,&prob); + free(dt->data_a); + free(dt->data_b); + free(dt->data_c); + free(dt); + return prob; +} + +int (*rate_predict)(RateData* data, int* sample_result, float* prob); +void setRatePredict(void* fn){ + rate_predict = fn; +} +float callRatePredict(double *data_a, double* data_b, double* data_c, int len_a, int len_b, int len_c){ + int sample_result=0; + float prob=0; + + RateData *dt= malloc(sizeof(RateData)); + + dt->data_a = (double*)malloc(sizeof(double)*len_a); + dt->data_b = (double*)malloc(sizeof(double)*len_b); + dt->data_c = (double*)malloc(sizeof(double)*len_c); + memcpy(dt->data_a, data_a, sizeof(double)*len_a); + memcpy(dt->data_b, data_b, sizeof(double)*len_b); + memcpy(dt->data_c, data_c, sizeof(double)*len_c); + dt->len_a = len_a; + dt->len_b = len_b; + dt->len_c = len_c; + + rate_predict(dt, &sample_result, &prob); + free(dt->data_a); + free(dt->data_b); + free(dt->data_c); + free(dt); + return prob; +}