从C语言向Golang传递uint8_t数组的方法
从C语言向Golang传递uint8_t数组的方法 大家好,
我是 Go 语言的新手 🙂,我想从 C 语言向 Go 语言发送一个 uint8_t 数组,但是当我以指针形式发送数组时,我不知道如何在 Go 中读取它并将其保存为 byte[] 数组类型。 以下是我的代码:
package main
/*
#include <stdint.h>
uint8_t Plaintext[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
uint8_t * send_data( )
{
return Plaintext;
}
*/
import "C"
import "unsafe"
import "fmt"
func main() {
data := [16]byte{}
p := C.send_data()
//already try data = C.send_data()
fmt.Println(p)
data = p // don't know how do this ?
}
目标是在 Go 中获得一个如下的字节数组:
data[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}
我尝试了很多解决方案,但每次都收到日志提示“无法使用 (func literal)() (类型 *_Ctype_uchar) 作为类型 “uint8” 或 “byte” …”。
谢谢大家的帮助!
更多关于从C语言向Golang传递uint8_t数组的方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html
你好 @skillian,
感谢你的回复,我使用了你描述的第二种解决方案,效果很好。
关于同一主题,我还有一个问题!你知道如何将变量放入数组的边界中吗?
替换这行:
p16byte := *((*[16]byte)(unsafe.Pointer(p)))
为:
int lens_var = 16
p16byte := *((*[lens_var]byte)(unsafe.Pointer(p)))
但这行不通,因为它无法编译。我也尝试使用切片,但同样不起作用:
int lens_var = 16
var type_var= make([]byte, lens_var )
p16byte := *((*type_var)(unsafe.Pointer(p)))
也许我忽略了一些细节!!!
再次感谢
更多关于从C语言向Golang传递uint8_t数组的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你好,Jawad,
你的 send_data 函数返回值的 Go 类型是 *_Ctype_uchar,它不能被直接赋值给一个 [16]byte 数组。有几种方法可以解决这个问题。一种方法是使用 unsafe.Pointer 类型配合 C.GoBytes 辅助函数:
package main
/*
#include <stdint.h>
uint8_t Plaintext[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
uint8_t * send_data( )
{
return Plaintext;
}
*/
import "C"
import "unsafe"
import "fmt"
func main() {
data := [16]byte{}
p := C.GoBytes(unsafe.Pointer(C.send_data()), 16)
fmt.Println(p)
copy(data[:], p)
fmt.Printf("%T: %v\n", data, data)
}
我认为这是正确的方法。另一种方法是转换那个 unsafe.Pointer,并直接将其转换为 *[16]byte:
package main
/*
#include <stdint.h>
uint8_t Plaintext[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
uint8_t * send_data( )
{
return Plaintext;
}
*/
import "C"
import "unsafe"
import "fmt"
func main() {
data := [16]byte{}
p := C.send_data()
fmt.Println(p)
p16byte := *((*[16]byte)(unsafe.Pointer(p)))
data = p16byte
fmt.Printf("%T: %v\n", data, data)
}
在Go中处理C返回的uint8_t*指针,可以通过unsafe.Pointer和切片转换实现。以下是修改后的代码:
package main
/*
#include <stdint.h>
uint8_t Plaintext[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
uint8_t* send_data() {
return Plaintext;
}
*/
import "C"
import (
"fmt"
"unsafe"
)
func main() {
// 获取C指针
cPtr := C.send_data()
// 将C指针转换为Go的unsafe.Pointer
ptr := unsafe.Pointer(cPtr)
// 创建指向16字节数组的指针
var data *[16]byte
data = (*[16]byte)(ptr)
// 打印结果
fmt.Printf("Data: %v\n", *data)
// 如果需要复制到新的Go数组(避免共享内存)
goArray := *data
fmt.Printf("Go array: %v\n", goArray)
// 或者直接作为切片使用
slice := (*data)[:]
fmt.Printf("Slice: %v\n", slice)
}
如果需要处理动态长度的数组,可以使用切片转换:
func main() {
cPtr := C.send_data()
ptr := unsafe.Pointer(cPtr)
// 假设已知长度为16
length := 16
// 转换为切片
slice := (*[1 << 30]byte)(ptr)[:length:length]
fmt.Printf("Slice (len=%d, cap=%d): %v\n",
len(slice), cap(slice), slice)
// 复制到新的Go切片(独立内存)
goSlice := make([]byte, length)
copy(goSlice, slice)
fmt.Printf("Copied slice: %v\n", goSlice)
}
注意:直接使用unsafe.Pointer转换访问C内存时,需要确保C内存的有效期。如果C函数返回的是局部变量的指针,可能会出现问题。

