猿问

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

使用cgo我正在调用c函数。我遇到了必须 C.int 地址复制到C.char[4]的情况。我可以在go中做到这一点吗?


代码片段 C- 结构:


struct data

{

    char    *a_add; 

    unsigned int length;

}

Go-Code


func 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 指针


我错过了什么?


绝地无双
浏览 146回答 1
1回答

叮当猫咪

您遇到的一个问题是,在对 C 代码的调用中,您可能无法将指针传递给 Go 指针。该变量是一个 ,但是一个 Go 指针,因此您不能使用它(或者更确切地说,您不能在 a_add 字段中将其用作值)。filedescriptorC.int&filedescriptor关于你的C代码有很多我不清楚的地方,但你可以使用下面的代码。请注意,对于您的特定情况,此代码可能有些过头了。它并不意味着特别高效或良好,在非常灵活的同时尽可能清晰 - 例如,它可以读取和写入打包的C结构。package main// #include <stdio.h>// #include <stdlib.h>// #include <string.h>//// struct data {//&nbsp; &nbsp; &nbsp;char *a_add;//&nbsp; &nbsp; &nbsp;unsigned int length;// };//// void f(struct data *p) {//&nbsp; &nbsp; printf("p->a_add = %p, p->length = %u\n", p->a_add, p->length);//&nbsp; &nbsp; printf("p->a_add as an int: %d\n", *(int *)p->a_add);//&nbsp; &nbsp; *(int *)p->a_add = 0x12345678;// }import "C"import (&nbsp; &nbsp; &nbsp; &nbsp; "fmt"&nbsp; &nbsp; &nbsp; &nbsp; "unsafe")const cIntSize = C.sizeof_int// Produce a Go int64 from a C int.&nbsp; The caller passes the address// of the C int.func int64FromCInt(ci unsafe.Pointer) int64 {&nbsp; &nbsp; &nbsp; &nbsp; // Get a slice pointing to the bytes of the C int.&nbsp; &nbsp; &nbsp; &nbsp; sci := (*[cIntSize]byte)(ci)[:]&nbsp; &nbsp; &nbsp; &nbsp; switch {&nbsp; &nbsp; &nbsp; &nbsp; case cIntSize == unsafe.Sizeof(int64(0)):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var gi int64&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sgi := (*[unsafe.Sizeof(gi)]byte)(unsafe.Pointer(&gi))[:]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; copy(sgi, sci)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return gi&nbsp; &nbsp; &nbsp; &nbsp; case cIntSize == unsafe.Sizeof(int32(0)):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var gi int32&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sgi := (*[unsafe.Sizeof(gi)]byte)(unsafe.Pointer(&gi))[:]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; copy(sgi, sci)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return int64(gi)&nbsp; &nbsp; &nbsp; &nbsp; case cIntSize == unsafe.Sizeof(int(0)):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var gi int&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sgi := (*[unsafe.Sizeof(gi)]byte)(unsafe.Pointer(&gi))[:]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; copy(sgi, sci)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return int64(gi)&nbsp; &nbsp; &nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; panic("no Go integer size matches C integer size")&nbsp; &nbsp; &nbsp; &nbsp; }}// Write C int (via an unsafe.Pointer) from Go int.&nbsp; The caller// passes the address of the C int.func writeCIntFromInt(gi int, ci unsafe.Pointer) {&nbsp; &nbsp; &nbsp; &nbsp; // Get a slices covering the bytes of the C int.&nbsp; &nbsp; &nbsp; &nbsp; sci := (*[cIntSize]byte)(ci)[:]&nbsp; &nbsp; &nbsp; &nbsp; switch {&nbsp; &nbsp; &nbsp; &nbsp; case cIntSize == unsafe.Sizeof(gi):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sgi := (*[unsafe.Sizeof(gi)]byte)(unsafe.Pointer(&gi))[:]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; copy(sci, sgi)&nbsp; &nbsp; &nbsp; &nbsp; case cIntSize == unsafe.Sizeof(int64(0)):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Copy value to int64 for copying purposes.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Since int64 holds all int values, this always works.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gi2 := int64(gi)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sgi := (*[unsafe.Sizeof(gi)]byte)(unsafe.Pointer(&gi2))[:]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; copy(sci, sgi)&nbsp; &nbsp; &nbsp; &nbsp; case cIntSize == unsafe.Sizeof(int32(0)):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Copy value to int32 for copying purposes.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Panic if we destroy the value via truncation.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gi2 := int32(gi)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if int(gi2) != gi {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 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))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sgi := (*[unsafe.Sizeof(gi)]byte)(unsafe.Pointer(&gi2))[:]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; copy(sci, sgi)&nbsp; &nbsp; &nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; panic("no Go integer size matches C integer size")&nbsp; &nbsp; &nbsp; &nbsp; }}func main() {&nbsp; &nbsp; &nbsp; &nbsp; b := C.malloc(cIntSize)&nbsp; &nbsp; &nbsp; &nbsp; defer C.free(b)&nbsp; &nbsp; &nbsp; &nbsp; writeCIntFromInt(32767, b)&nbsp; &nbsp; &nbsp; &nbsp; d := C.struct_data{a_add: (*C.char)(b), length: cIntSize}&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("calling C.f(d)")&nbsp; &nbsp; &nbsp; &nbsp; C.f(&d)&nbsp; &nbsp; &nbsp; &nbsp; result := int64FromCInt(unsafe.Pointer(d.a_add))&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("result = %#x\n", result)}
随时随地看视频慕课网APP

相关分类

Go
我要回答