为了账号安全,请及时绑定邮箱和手机立即绑定

如何将 C.int 地址复制到cgo中的C.char中?

如何将 C.int 地址复制到cgo中的C.char中?

Go
绝地无双 2022-08-24 15:38:08
使用cgo我正在调用c函数。我遇到了必须 C.int 地址复制到C.char[4]的情况。我可以在go中做到这一点吗?代码片段 C- 结构:struct data{    char    *a_add;     unsigned int length;}Go-Codefunc main() {     var d[3] C.data     var filedescriptor C.int     d[0].a_add = &filedescriptor      d[0].length = 4}问题是a_add是一个字符*。但是我需要传递int变量地址。c代码是遗留代码,我现在无法修复数据类型。其他C模块使用它,并且它在C中工作并发出警告。在去的地方,这是错误。有没有办法将int变量的地址复制到cgo中的char*数组中。更新:我尝试了d[0].a_add = (*C.char)(不安全。Pointer(&filedescriptor )),获取错误:死机:运行时错误:cgo 参数具有指向 Go 指针的 Go 指针我错过了什么?
查看完整描述

1 回答

?
叮当猫咪

TA贡献1776条经验 获得超12个赞

您遇到的一个问题是,在对 C 代码的调用中,您可能无法将指针传递给 Go 指针。该变量是一个 ,但是一个 Go 指针,因此您不能使用它(或者更确切地说,您不能在 a_add 字段中将其用作值)。filedescriptorC.int&filedescriptor


关于你的C代码有很多我不清楚的地方,但你可以使用下面的代码。请注意,对于您的特定情况,此代码可能有些过头了。它并不意味着特别高效或良好,在非常灵活的同时尽可能清晰 - 例如,它可以读取和写入打包的C结构。


package main


// #include <stdio.h>

// #include <stdlib.h>

// #include <string.h>

//

// struct data {

//     char *a_add;

//     unsigned int length;

// };

//

// void f(struct data *p) {

//    printf("p->a_add = %p, p->length = %u\n", p->a_add, p->length);

//    printf("p->a_add as an int: %d\n", *(int *)p->a_add);

//    *(int *)p->a_add = 0x12345678;

// }

import "C"


import (

        "fmt"

        "unsafe"

)


const cIntSize = C.sizeof_int


// Produce a Go int64 from a C int.  The caller passes the address

// of the C int.

func int64FromCInt(ci unsafe.Pointer) int64 {

        // Get a slice pointing to the bytes of the C int.

        sci := (*[cIntSize]byte)(ci)[:]

        switch {

        case cIntSize == unsafe.Sizeof(int64(0)):

                var gi int64

                sgi := (*[unsafe.Sizeof(gi)]byte)(unsafe.Pointer(&gi))[:]

                copy(sgi, sci)

                return gi

        case cIntSize == unsafe.Sizeof(int32(0)):

                var gi int32

                sgi := (*[unsafe.Sizeof(gi)]byte)(unsafe.Pointer(&gi))[:]

                copy(sgi, sci)

                return int64(gi)

        case cIntSize == unsafe.Sizeof(int(0)):

                var gi int

                sgi := (*[unsafe.Sizeof(gi)]byte)(unsafe.Pointer(&gi))[:]

                copy(sgi, sci)

                return int64(gi)

        default:

                panic("no Go integer size matches C integer size")

        }

}


// Write C int (via an unsafe.Pointer) from Go int.  The caller

// passes the address of the C int.

func writeCIntFromInt(gi int, ci unsafe.Pointer) {

        // Get a slices covering the bytes of the C int.

        sci := (*[cIntSize]byte)(ci)[:]

        switch {

        case cIntSize == unsafe.Sizeof(gi):

                sgi := (*[unsafe.Sizeof(gi)]byte)(unsafe.Pointer(&gi))[:]

                copy(sci, sgi)

        case cIntSize == unsafe.Sizeof(int64(0)):

                // Copy value to int64 for copying purposes.

                // Since int64 holds all int values, this always works.

                gi2 := int64(gi)

                sgi := (*[unsafe.Sizeof(gi)]byte)(unsafe.Pointer(&gi2))[:]

                copy(sci, sgi)

        case cIntSize == unsafe.Sizeof(int32(0)):

                // Copy value to int32 for copying purposes.

                // Panic if we destroy the value via truncation.

                gi2 := int32(gi)

                if int(gi2) != gi {

                        panic(fmt.Sprintf("unable to send Go value %x to C: size of Go int=%d, size of C int=%d", gi, unsafe.Sizeof(gi), cIntSize))

                }

                sgi := (*[unsafe.Sizeof(gi)]byte)(unsafe.Pointer(&gi2))[:]

                copy(sci, sgi)

        default:

                panic("no Go integer size matches C integer size")

        }

}


func main() {

        b := C.malloc(cIntSize)

        defer C.free(b)

        writeCIntFromInt(32767, b)

        d := C.struct_data{a_add: (*C.char)(b), length: cIntSize}

        fmt.Println("calling C.f(d)")

        C.f(&d)

        result := int64FromCInt(unsafe.Pointer(d.a_add))

        fmt.Printf("result = %#x\n", result)

}



查看完整回答
反对 回复 2022-08-24
  • 1 回答
  • 0 关注
  • 145 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号