cgo与c转换 - Fri, Sep 13, 2024
cgo与c转换
1. 基本用法
package cgoexample
/*
##include <stdio.h>
##include <stdlib.h>
void myprint(char* s) {
printf("%s\n", s);
}
*/
import "C"
import "unsafe"
func Example() {
cs := C.CString("Hello from stdio\n")
C.myprint(cs)
C.free(unsafe.Pointer(cs))
}
2. 全局函数
xxx.go
package gocallback
import "fmt"
/*
##include <stdio.h>
extern void ACFunction();
*/
import "C"
//export AGoFunction
func AGoFunction() {
fmt.Println("AGoFunction()")
}
func Example() {
C.ACFunction()
}
xxx.c
#include "_cgo_export.h"
void ACFunction() {
printf("ACFunction()\n");
AGoFunction();
}
3. 函数变量
函数作为变量在cgo和c之间传递
package main
import (
"fmt"
"runtime/cgo"
)
/*
##include <stdint.h>
extern void go_callback_int(uintptr_t h, int p1);
static inline void CallMyFunction(uintptr_t h) {
go_callback_int(h, 5);
}
*/
import "C"
//export go_callback_int
func go_callback_int(h C.uintptr_t, p1 C.int) {
fn := cgo.Handle(h).Value().(func(C.int))
fn(p1)
}
func MyCallback(x C.int) {
fmt.Println("callback with", x)
}
func main() {
h := cgo.NewHandle(MyCallback)
C.CallMyFunction(C.uintptr_t(h))
h.Delete()
}
4. 函数回调
xxx.go
package main
/*
##cgo CFLAGS: -I .
##cgo LDFLAGS: -L . -lclibrary
##include "clibrary.h"
int callOnMeGo_cgo(int in); // Forward declaration.
*/
import "C"
import (
"fmt"
"unsafe"
)
//export callOnMeGo
func callOnMeGo(in int) int {
fmt.Printf("Go.callOnMeGo(): called with arg = %d\n", in)
return in + 1
}
func main() {
fmt.Printf("Go.main(): calling C function with callback to us\n")
C.some_c_func((C.callback_fcn)(unsafe.Pointer(C.callOnMeGo_cgo)))
}
xxx_c.go
作为cgo和c之间的胶水文件,将cgo导出的函数,以c函数的方式重新定义.
xxx_c.go
package main
/*
##include <stdio.h>
// The gateway function
int callOnMeGo_cgo(int in)
{
printf("C.callOnMeGo_cgo(): called with arg = %d\n", in);
int callOnMeGo(int);
return callOnMeGo(in);
}
*/
import "C"
5. 数组
使用unsafe.Slice将c数组指针转为cgo切片
import "C"
import "unsafe"
func main() {
var theCArray *C.YourType = C.getTheArray()
length := C.getTheArrayLength()
slice := unsafe.Slice(theCArray, length)
}
使用强转将cgo数组转c数组指针
import "C"
func main() {
slice := make([]*C.YourType, length)
var theCArray *C.YourType = unsafe.SliceData(slice)
}