kaisawind's blog
  • 关于
  • 所有帖子

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)
}


辽ICP备2021007608号 | © 2025 | kaisawind

Facebook Twitter GitHub