douzhan1994 2018-11-28 03:03
浏览 522
已采纳

将* C.uint8_t转换为[] uint8是否安全?

I'm trying to pass uint8_t array from C code to Go, then read some bytes from file and store them into this array in Go code.

Sample code is here.

main.c :

#define BUFFER_SIZE 16384

int read_go(uint8_t* buffer, int bufferSize);

void read_buf() {
     uint8_t* buffer = (uint8_t*)malloc(BUFFER_SIZE);
     read_go(buffer, BUFFER_SIZE)

     // do something with buffer

     free(buffer)
}

read.go :

 /*
 #include "main.c"

 extern int read_go(uint8_t* buffer, int bufferSize);
 */
 import "C"

 //export read_go
 func read_go(buffer *C.uint8_t, bufferSize C.int) C.int {
      f, _ := os.Open("filename")
      defer f.close()

      buff := *(*[]uint8)(unsafe.Pointer(&buffer))
      n, _ := f.Read(buff)

      return C.int(n)
 }

It works well, but I'm worrying about segmentation fault. Because I cannot specify the buffer size at Read function unlike fread function of C.

I know that Read function reads bytes from file as much as len(buff). But I cannot guarantee that len(buff) is the same as bufferSize.

Is it safe to convert *C.uint8_t to []uint8?

  • 写回答

1条回答 默认 最新

  • douduoting8408 2018-11-28 15:33
    关注

    Your code is wrong.

    A Go slice is implemented as a Go struct:

    type slice struct {
        array unsafe.Pointer
        len   int
        cap   int
    }
    

    Your values for slice.len and slice.cap are undefined.


    Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself.

    Your code fragments don't compile and are incomplete.


    buf is a Go byte slice to satisfy io.Reader.

    type Reader interface {
        Read(p []byte) (n int, err error)
    }
    
    buffer *C.uint8_t
    bufferSize C.int
    
    buf := (*[1 << 30]byte)(unsafe.Pointer(buffer))[:bufferSize:bufferSize]
    n, err := f.Read(buf)
    

    Here is my solution in reproducible form.

    main.c:

    #include <stdint.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    #define BUFFER_SIZE 16384
    
    int read_go(uint8_t* buffer, int bufferSize);
    
    void read_buf() {
        uint8_t* buffer = (uint8_t*)malloc(BUFFER_SIZE+1);
        buffer[BUFFER_SIZE]='\0';
        int n = read_go(buffer, BUFFER_SIZE);
        if (n < 0) {
            printf("read_go: error: %d
    ", n);
            n = 0;
        }
        if (n > BUFFER_SIZE) {
            n = BUFFER_SIZE;
        }
        buffer[n] = '\0';
    
        // do something with buffer
        int width = n;
        printf("%d
    ", width);
        if (width > 16) {
            width = 16;
        }
        for (int i = 0; i < width; i++)     {
            printf("%02X", buffer[i]);
        }
        printf("
    ");
        for (int i = 0; i < width; i++)     {
            printf("%-2c", buffer[i]);
        }
        printf("
    ");
    
        free(buffer);
    }
    
    int main(int argc, char *argv[]) {
        read_buf();
        return EXIT_SUCCESS;
    }
    

    read.go:

    package main
    
    /*
    #include <stdint.h>
    */
    import "C"
    
    import (
        "os"
        "unsafe"
    )
    
    //export read_go
    func read_go(buffer *C.uint8_t, bufferSize C.int) C.int {
        f, err := os.Open("filename")
        if err != nil {
            return C.int(-1)
        }
        defer f.Close()
    
        buf := (*[1 << 30]byte)(unsafe.Pointer(buffer))[:bufferSize:bufferSize]
        n, err := f.Read(buf)
        if err != nil {
            return C.int(-1)
        }
        return C.int(n)
    }
    
    func main() {}
    

    Output (Linux):

    $ cat filename
    filedata 01234567890
    $ export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH
    $ go build -a -o libread.so -buildmode=c-shared read.go
    $ gcc main.c libread.so -o read && ./read
    21
    66696C65646174612030313233343536
    f i l e d a t a   0 1 2 3 4 5 6 
    $ 
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog