C语言适配¶
更新于: 2018.08.20
调用C编写的动态库¶
设动态库名为libtest.so, 在/zzq/lib/下. 暴露以下接口:
int CreateTester(const char* path, const char* binpath, void** handle);
int Test(void* handle, const char* path, int ids[], char **result, size_t *len);
const char* GetErrorMessage(int err);
int DeleteTester(void* handle);
适配代码如下, 注意对C数组, 指针, 指针的指针, void**等元素的适配:
package demo
/*
#cgo LDFLAGS: -L/zzq/lib -ltest -ldl
#include <stdlib.h>
int CreateTester(const char* path, const char* binpath, void** handle);
int Test(void* handle, const char* path, int ids[], char **result, size_t *len);
const char* GetErrorMessage(int err);
int DeleteTester(void* handle);
*/
import "C"
import (
"fmt"
"unsafe"
)
type Tester struct {
handle unsafe.Pointer
}
const (
// TEST_ERROR_SUCCESS 表示成功的错误码
TEST_ERROR_SUCCESS int = 0
)
// GetError 返回错误码对应的错误消息字符串
func GetError(err int) string {
c := C.GetErrorMessage(C.int(err))
return C.GoString(c)
}
// Create 创建实例
func Create(path string, binpath string) (*Tester, error) {
if path == "" || binpath == "" {
return nil, fmt.Errorf("tester: invalid argument")
}
var p unsafe.Pointer
c1 := C.CString(path)
c2 := C.CString(binpath)
defer C.free(unsafe.Pointer(c1))
defer C.free(unsafe.Pointer(c2))
ret := C.CreateTester(c1, c2, &p)
if int(ret) != TEST_ERROR_SUCCESS {
return nil, fmt.Errorf("tester: create failed: %s", GetError(int(ret)))
}
t := new(Tester)
t.handle = p
return t, nil
}
// Destroy 销毁实例
func (t *Tester) Destroy() error {
if t.handle == nil {
return nil
}
C.DeleteTester(t.handle)
return nil
}
// 处理文件
func (t *Tester) Test(path string, ids []int) (string, error) {
if t.handle == nil {
return "", fmt.Errorf("tester: invalid handle")
}
c := C.CString(path)
defer C.free(unsafe.Pointer(c))
var res *C.char = nil
var l C.size_t
ret := C.Test(t.handle, c, (*C.int)(unsafe.Pointer(&ids[0])), &res, &l)
if int(ret) != TEST_ERROR_SUCCESS {
if res != nil {
C.free(unsafe.Pointer(res))
}
return "", fmt.Errorf("tester: test failed: %s", GetError(int(ret)))
}
if res != nil {
s := C.GoString(res)
C.free(unsafe.Pointer(res))
return s, nil
}
return "", fmt.Errorf("tester: test failed, unknown error")
}