编译 *.so 的动态链接
最后更新于:2022-04-02 02:51:09
[TOC]
## 概述
c-shared模式的golang模块支持c,python,java,nodejs、lua、ruby、Julia等语言的调用
## 示例
### 生成 `awesome.so`
生成 `awesome.so` 文件 ``` go build -o awesome.so -buildmode=c-shared awesome.go ``` 编译后生成如下两个文件:`awesome.h`,`awesome.h` ### c语言动态链接调用
#include "awesome.h"
int main() {
//Call Add() - passing integer params, interger result
GoInt a = 12;
GoInt b = 99;
printf("awesome.Add(12,99) = %d\n", Add(a, b));
//Call Cosine() - passing float param, float returned
printf("awesome.Cosine(1) = %f\n", (float)(Cosine(1.0)));
//Call Sort() - passing an array pointer
GoInt data[6] = {77, 12, 5, 99, 28, 23};
GoSlice nums = {data, 6, 6};
Sort(nums);
printf("awesome.Sort(77,12,5,99,28,23): ");
for (int i = 0; i < 6; i++){
printf("%d,", ((GoInt *)nums.data)[i]);
}
printf("\n");
//Call Log() - passing string value
GoString msg = {"Hello from C!", 13};
Log(msg);
}
```
执行 ``` $> gcc -o client client1.c ./awesome.so $> ./client awesome.Add(12,99) = 111 awesome.Cosine(1) = 0.540302 awesome.Sort(77,12,5,99,28,23): 5,12,23,28,77,99, Hello from C! ``` ### c语言动态加载
#include
#include
// define types needed
typedef long long go_int;
typedef double go_float64;
typedef struct{void *arr; go_int len; go_int cap;} go_slice;
typedef struct{const char *p; go_int len;} go_str;
int main(int argc, char **argv) {
void *handle;
char *error;
// use dlopen to load shared object
handle = dlopen ("./awesome.so", RTLD_LAZY);
if (!handle) {
fputs (dlerror(), stderr);
exit(1);
}
// resolve Add symbol and assign to fn ptr
go_int (*add)(go_int, go_int) = dlsym(handle, "Add");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(1);
}
// call Add()
go_int sum = (*add)(12, 99);
printf("awesome.Add(12, 99) = %d\n", sum);
// resolve Cosine symbol
go_float64 (*cosine)(go_float64) = dlsym(handle, "Cosine");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(1);
}
// Call Cosine
go_float64 cos = (*cosine)(1.0);
printf("awesome.Cosine(1) = %f\n", cos);
// resolve Sort symbol
void (*sort)(go_slice) = dlsym(handle, "Sort");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(1);
}
// call Sort
go_int data[5] = {44,23,7,66,2};
go_slice nums = {data, 5, 5};
sort(nums);
printf("awesome.Sort(44,23,7,66,2): ");
for (int i = 0; i < 5; i++){
printf("%d,", ((go_int *)data)[i]);
}
printf("\n");
// resolve Log symbol
go_int (*log)(go_str) = dlsym(handle, "Log");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(1);
}
// call Log
go_str msg = {"Hello from C!", 13};
log(msg);
// close file handle when done
dlclose(handle);
}
```
执行 ``` $> gcc -o client client2.c -ldl $> ./client awesome.Add(12, 99) = 111 awesome.Cosine(1) = 0.540302 awesome.Sort(44,23,7,66,2): 2,7,23,44,66, Hello from C! ``` ### python ctypes 方式调用
### java调用
';
awesome.go
``` package main import "C" import ( "fmt" "math" "sort" "sync" ) var count int var mtx sync.Mutex //export Add func Add(a, b int) int { return a + b } //export Cosine func Cosine(x float64) float64 { return math.Cos(x) } //export Sort func Sort(vals []int) { sort.Ints(vals) } //export Log func Log(msg string) int { mtx.Lock() defer mtx.Unlock() fmt.Println(msg) count++ return count } // 必须声明 func main() { } ```生成 `awesome.so` 文件 ``` go build -o awesome.so -buildmode=c-shared awesome.go ``` 编译后生成如下两个文件:`awesome.h`,`awesome.h` ### c语言动态链接调用
client1.c
``` #include执行 ``` $> gcc -o client client1.c ./awesome.so $> ./client awesome.Add(12,99) = 111 awesome.Cosine(1) = 0.540302 awesome.Sort(77,12,5,99,28,23): 5,12,23,28,77,99, Hello from C! ``` ### c语言动态加载
client2.c
``` #include执行 ``` $> gcc -o client client2.c -ldl $> ./client awesome.Add(12, 99) = 111 awesome.Cosine(1) = 0.540302 awesome.Sort(44,23,7,66,2): 2,7,23,44,66, Hello from C! ``` ### python ctypes 方式调用
client.py
``` from ctypes import * lib = cdll.LoadLibrary("./awesome.so") # describe and invoke Add() lib.Add.argtypes = [c_longlong, c_longlong] lib.Add.restype = c_longlong print "awesome.Add(12,99) = %d" % lib.Add(12,99) # describe and invoke Cosine() lib.Cosine.argtypes = [c_double] lib.Cosine.restype = c_double print "awesome.Cosine(1) = %f" % lib.Cosine(1) # define class GoSlice to map to: # C type struct { void *data; GoInt len; GoInt cap; } class GoSlice(Structure): _fields_ = [("data", POINTER(c_void_p)), ("len", c_longlong), ("cap", c_longlong)] nums = GoSlice((c_void_p * 5)(74, 4, 122, 9, 12), 5, 5) # call Sort lib.Sort.argtypes = [GoSlice] lib.Sort.restype = None lib.Sort(nums) print "awesome.Sort(74,4,122,9,12) = [", for i in range(nums.len): print "%d "% nums.data[i], print "]" # define class GoString to map: # C type struct { const char *p; GoInt n; } class GoString(Structure): _fields_ = [("p", c_char_p), ("n", c_longlong)] # describe and call Log() lib.Log.argtypes = [GoString] lib.Log.restype = c_longlong msg = GoString(b"Hello Python!", 13) print "log id %d"% lib.Log(msg) ```### java调用