Go语言到C语言的结构体指针和整型指针

1、Go -> C结构体

package main
/*
#include <stdlib.h>
#include <stdio.h>

struct MyString
{
	char* s;
	int len;
};

struct MyString xmalloc(int len)
{
	static const char* s = "0123456789";
	char* p = malloc(len);
	if (len <= strlen(s)) {
		memcpy(p, s, len);
	} else {
		memset(p, 'a', len);
	}

	struct MyString str;
	str.s = p;
	str.len = len;
	return str;
}
*/
import "C"
import (
	"fmt"
	"unsafe"
)

func main() {
	len := 10
	str := C.xmalloc(C.int(len))
	defer C.free(unsafe.Pointer(str.s))
	gostr := C.GoStringN(str.s, str.len)
	fmt.Printf("retlen=%v\n", str.len)
	println(gostr)
}

结果:

retlen=10
0123456789

你可以将整个golang的结构体指针转换成c语言的结构体指针,前提是golang 的结构体和c 的结构体定义是一一对应的(后面有介绍怎么穿件一一对应的结构体),但是c语言的结构体指针无法直接转换成golang语言的结构体指针:

package main
 
import (
 "fmt"
 "unsafe"
)
 
// struct x {
//  int y, z;
// };
//
// int sum(struct x a) {
//  return a.y + a.z;
// }
//
import "C"
 
type X struct{ Y, Z int32 }
 
func main() {
    a := &X{5, 7}
    fmt.Println(a, "->", C.sum(*((*C.struct_x)(unsafe.Pointer(a)))))
}

cgo -godefs 是专门用来将c语言结构体转换成golang语言对应的结构体的工具。

 package main

/*
#include <stdio.h>

typedef struct {
    int a;
    int b;
} Foo;

void pass_struct(Foo *in) { printf("%d : %d\n", in->a, in->b); }

void pass_array(Foo **in, int len) {
    for(int i = 0; i < len; i++) {
        pass_struct(in[i]);
        in[i]->a += 1;
        in[i]->b += 1;
    }
}
*/
import "C"

import (
    "fmt"
    "unsafe"
)

type Foo struct{ a, b int32 }

func main() {
    foo := Foo{10, 20}
    foos := []*Foo{&Foo{1, 2}, &Foo{3, 4}}

    fmt.Println("from C land")
    C.pass_struct((*C.Foo)(unsafe.Pointer(&foo)))
    C.pass_array((**C.Foo)(unsafe.Pointer(&foos[0])), C.int(len(foos)))
    fmt.Println("a & b should have incremented with 1")

    fmt.Println("from Go land")
    for _, foo := range foos {
        fmt.Printf("%d : %d\n", foo.a, foo.b)
    }
}

Output:

from C land
10 : 20
1 : 2
3 : 4
a & b should have incremented with 1
from Go land
2 : 3
4 : 5

2、Go -> C 整形指针

package main
 /*
#include <stdlib.h>
#include <stdio.h>
char* xmalloc(int len, int *rlen)
{
	static const char* s = "0123456789";
	char* p = malloc(len);
	if (len <= strlen(s)) {
		memcpy(p, s, len);
	} else {
		memset(p, 'a', len);
	}
	*rlen = len;
	return p;
}
*/
import "C"
import (
	"fmt"
	"unsafe"
)

func main() {

	rlen := C.int(0)
	len := 10
	cstr := C.xmalloc(C.int(len), &rlen)

	defer C.free(unsafe.Pointer(cstr))
	gostr := C.GoStringN(cstr, rlen)
	fmt.Printf("retlen=%v\n", rlen)
	println(gostr)
}

xmalloc函数的第二个参数是int*,这里设计为一个输入、输出参数。我们在Golang中使用C.int类型的指针就可以;

其返回值是一个char*,在Golang中就是 *C.char,由于返回值是指针,其内存由malloc分配,因此需要在Golang中对其内存进行释放。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绛洞花主敏明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值