Функция C.CBytes

Функция C.CBytes преобразует данные из памяти Go в байтовый массив C. Она принимает один параметр - срез байтов []byte, содержащий данные для копирования, и возвращает указатель на массив байтов C типа unsafe.Pointer. Эта функция полезна при передаче бинарных данных из Go в C-функции.

Синтаксис

goC.CBytes([]byte data)

Пример

Давайте преобразуем строку в байтовый массив и передадим его в C-функцию:

gopackage main

/*
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

void printBytes(void *data, int length) {
  unsigned char *bytes = (unsigned char*)data;
  for (int i = 0; i < length; i++) {
    printf("%02x ", bytes[i]);
  }
  printf("\n");
}
*/
import "C"
import "fmt"

func main() {
  str := "abcde"
  data := []byte(str)
  
  // Преобразуем данные в C-массив
  cData := C.CBytes(data)
  defer C.free(cData)
  
  // Вызываем C-функцию для вывода байтов
  C.printBytes(cData, C.int(len(data)))
  fmt.Println("Done")
}

Результат выполнения кода:

go61 62 63 64 65
Done

Пример

Давайте передадим байтовый массив в C-функцию для обработки данных:

gopackage main

/*
#include <stdlib.h>
#include <string.h>

int sumBytes(void *data, int length) {
  unsigned char *bytes = (unsigned char*)data;
  int sum = 0;
  for (int i = 0; i < length; i++) {
    sum += bytes[i];
  }
  return sum;
}
*/
import "C"
import "fmt"

func main() {
  // Создаем слайс байтов
  bytes := []byte{1, 2, 3, 4, 5}
  
  // Преобразуем в C-массив
  cBytes := C.CBytes(bytes)
  defer C.free(cBytes)
  
  // Вызываем C-функцию для суммирования
  result := C.sumBytes(cBytes, C.int(len(bytes)))
  fmt.Println(result)
}

Результат выполнения кода:

go15

Пример

Давайте преобразуем структуру данных в байтовый массив для передачи в C:

gopackage main

/*
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

typedef struct {
  int32_t id;
  double value;
} Item;

void processItem(void *data) {
  Item *item = (Item*)data;
  item->value *= 2.0;
}
*/
import "C"
import (
  "encoding/binary"
  "fmt"
  "unsafe"
)

func main() {
  // Создаем структуру
  id := int32(42)
  value := 3.14
  
  // Создаем буфер для байтов
  buf := make([]byte, 12) // 4 байта для int32 + 8 байт для double
  binary.LittleEndian.PutUint32(buf[0:4], uint32(id))
  binary.LittleEndian.PutUint64(buf[4:12], uint64(value))
  
  // Преобразуем в C-массив
  cData := C.CBytes(buf)
  defer C.free(cData)
  
  // Вызываем C-функцию для обработки
  C.processItem(cData)
  
  // Читаем результат обратно
  newID := int32(binary.LittleEndian.Uint32(buf[0:4]))
  newValue := float64(binary.LittleEndian.Uint64(buf[4:12]))
  
  fmt.Printf("ID: %d, Value: %.2f\n", newID, newValue)
}

Результат выполнения кода:

goID: 42, Value: 6.28

Смотрите также

  • функцию C.GoBytes,
    которая преобразует массив C обратно в срез байтов Go
  • функцию C.CString,
    которая преобразует строку Go в C-строку
  • функцию C.free,
    которая освобождает память, выделенную через C.CBytes
  • раздел указатели в CGO,
    в котором описаны правила работы с указателями в CGO