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












3















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?










share|improve this question

























  • It's always unsafe, as indicated by the use of the unsafe package, but you still need to use it to convert types from C. You have the bufferSize value right there though, so what do you mean that you can't specify it?

    – JimB
    Nov 28 '18 at 15:09











  • I don't know if you built this on Linux or other Unix-like, but naming your function read is going to conflict with the system C library. Yours will take priority but other code that wants to read things will likely call your function. With the wrong arguments. Chaos and destruction will ensue.

    – Zan Lynx
    Nov 28 '18 at 16:18













  • @ZanLynx I'm working on MAC, so it is Unix. But the code above is just a sample, I didn't consider about that. The name of the function in real code is not 'read'. Thank you for your comment.

    – Junghoon Jang
    Nov 29 '18 at 2:41











  • @JimB I mean I cannot specify the size of buffer when I do n, _ := f.Read(buff). Usually, in C code, we can put the size of buffer as a parameter in the read functions.

    – Junghoon Jang
    Nov 29 '18 at 2:45
















3















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?










share|improve this question

























  • It's always unsafe, as indicated by the use of the unsafe package, but you still need to use it to convert types from C. You have the bufferSize value right there though, so what do you mean that you can't specify it?

    – JimB
    Nov 28 '18 at 15:09











  • I don't know if you built this on Linux or other Unix-like, but naming your function read is going to conflict with the system C library. Yours will take priority but other code that wants to read things will likely call your function. With the wrong arguments. Chaos and destruction will ensue.

    – Zan Lynx
    Nov 28 '18 at 16:18













  • @ZanLynx I'm working on MAC, so it is Unix. But the code above is just a sample, I didn't consider about that. The name of the function in real code is not 'read'. Thank you for your comment.

    – Junghoon Jang
    Nov 29 '18 at 2:41











  • @JimB I mean I cannot specify the size of buffer when I do n, _ := f.Read(buff). Usually, in C code, we can put the size of buffer as a parameter in the read functions.

    – Junghoon Jang
    Nov 29 '18 at 2:45














3












3








3


1






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?










share|improve this question
















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?







c go cgo






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 29 '18 at 2:49







Junghoon Jang

















asked Nov 28 '18 at 3:03









Junghoon JangJunghoon Jang

214




214













  • It's always unsafe, as indicated by the use of the unsafe package, but you still need to use it to convert types from C. You have the bufferSize value right there though, so what do you mean that you can't specify it?

    – JimB
    Nov 28 '18 at 15:09











  • I don't know if you built this on Linux or other Unix-like, but naming your function read is going to conflict with the system C library. Yours will take priority but other code that wants to read things will likely call your function. With the wrong arguments. Chaos and destruction will ensue.

    – Zan Lynx
    Nov 28 '18 at 16:18













  • @ZanLynx I'm working on MAC, so it is Unix. But the code above is just a sample, I didn't consider about that. The name of the function in real code is not 'read'. Thank you for your comment.

    – Junghoon Jang
    Nov 29 '18 at 2:41











  • @JimB I mean I cannot specify the size of buffer when I do n, _ := f.Read(buff). Usually, in C code, we can put the size of buffer as a parameter in the read functions.

    – Junghoon Jang
    Nov 29 '18 at 2:45



















  • It's always unsafe, as indicated by the use of the unsafe package, but you still need to use it to convert types from C. You have the bufferSize value right there though, so what do you mean that you can't specify it?

    – JimB
    Nov 28 '18 at 15:09











  • I don't know if you built this on Linux or other Unix-like, but naming your function read is going to conflict with the system C library. Yours will take priority but other code that wants to read things will likely call your function. With the wrong arguments. Chaos and destruction will ensue.

    – Zan Lynx
    Nov 28 '18 at 16:18













  • @ZanLynx I'm working on MAC, so it is Unix. But the code above is just a sample, I didn't consider about that. The name of the function in real code is not 'read'. Thank you for your comment.

    – Junghoon Jang
    Nov 29 '18 at 2:41











  • @JimB I mean I cannot specify the size of buffer when I do n, _ := f.Read(buff). Usually, in C code, we can put the size of buffer as a parameter in the read functions.

    – Junghoon Jang
    Nov 29 '18 at 2:45

















It's always unsafe, as indicated by the use of the unsafe package, but you still need to use it to convert types from C. You have the bufferSize value right there though, so what do you mean that you can't specify it?

– JimB
Nov 28 '18 at 15:09





It's always unsafe, as indicated by the use of the unsafe package, but you still need to use it to convert types from C. You have the bufferSize value right there though, so what do you mean that you can't specify it?

– JimB
Nov 28 '18 at 15:09













I don't know if you built this on Linux or other Unix-like, but naming your function read is going to conflict with the system C library. Yours will take priority but other code that wants to read things will likely call your function. With the wrong arguments. Chaos and destruction will ensue.

– Zan Lynx
Nov 28 '18 at 16:18







I don't know if you built this on Linux or other Unix-like, but naming your function read is going to conflict with the system C library. Yours will take priority but other code that wants to read things will likely call your function. With the wrong arguments. Chaos and destruction will ensue.

– Zan Lynx
Nov 28 '18 at 16:18















@ZanLynx I'm working on MAC, so it is Unix. But the code above is just a sample, I didn't consider about that. The name of the function in real code is not 'read'. Thank you for your comment.

– Junghoon Jang
Nov 29 '18 at 2:41





@ZanLynx I'm working on MAC, so it is Unix. But the code above is just a sample, I didn't consider about that. The name of the function in real code is not 'read'. Thank you for your comment.

– Junghoon Jang
Nov 29 '18 at 2:41













@JimB I mean I cannot specify the size of buffer when I do n, _ := f.Read(buff). Usually, in C code, we can put the size of buffer as a parameter in the read functions.

– Junghoon Jang
Nov 29 '18 at 2:45





@JimB I mean I cannot specify the size of buffer when I do n, _ := f.Read(buff). Usually, in C code, we can put the size of buffer as a parameter in the read functions.

– Junghoon Jang
Nov 29 '18 at 2:45












1 Answer
1






active

oldest

votes


















4














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]='';
int n = read_go(buffer, BUFFER_SIZE);
if (n < 0) {
printf("read_go: error: %dn", n);
n = 0;
}
if (n > BUFFER_SIZE) {
n = BUFFER_SIZE;
}
buffer[n] = '';

// do something with buffer
int width = n;
printf("%dn", width);
if (width > 16) {
width = 16;
}
for (int i = 0; i < width; i++) {
printf("%02X", buffer[i]);
}
printf("n");
for (int i = 0; i < width; i++) {
printf("%-2c", buffer[i]);
}
printf("n");

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
$





share|improve this answer


























  • So just to clarify: You are casting the buffer pointer into a Go pointer to a byte array of size 1 << 30 (big but not the maximum, just a convenient shift size, and a constant) and then creating a slice of that imaginary buffer.

    – Zan Lynx
    Nov 28 '18 at 16:16











  • @ZanLynx: Exactly. "The length is part of the [Go] array's type; it must evaluate to a non-negative [compile-time] constant representable by a value of type int.": Array types, The Go Programming Language Specification. So we need some trickery. Array length constant 1 << 30 is a simple way of describing a very large Go byte array that is handled by 32-bit int implementations.

    – peterSO
    Nov 28 '18 at 16:30













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53511478%2fis-it-safe-to-convert-c-uint8-t-to-uint8%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









4














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]='';
int n = read_go(buffer, BUFFER_SIZE);
if (n < 0) {
printf("read_go: error: %dn", n);
n = 0;
}
if (n > BUFFER_SIZE) {
n = BUFFER_SIZE;
}
buffer[n] = '';

// do something with buffer
int width = n;
printf("%dn", width);
if (width > 16) {
width = 16;
}
for (int i = 0; i < width; i++) {
printf("%02X", buffer[i]);
}
printf("n");
for (int i = 0; i < width; i++) {
printf("%-2c", buffer[i]);
}
printf("n");

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
$





share|improve this answer


























  • So just to clarify: You are casting the buffer pointer into a Go pointer to a byte array of size 1 << 30 (big but not the maximum, just a convenient shift size, and a constant) and then creating a slice of that imaginary buffer.

    – Zan Lynx
    Nov 28 '18 at 16:16











  • @ZanLynx: Exactly. "The length is part of the [Go] array's type; it must evaluate to a non-negative [compile-time] constant representable by a value of type int.": Array types, The Go Programming Language Specification. So we need some trickery. Array length constant 1 << 30 is a simple way of describing a very large Go byte array that is handled by 32-bit int implementations.

    – peterSO
    Nov 28 '18 at 16:30


















4














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]='';
int n = read_go(buffer, BUFFER_SIZE);
if (n < 0) {
printf("read_go: error: %dn", n);
n = 0;
}
if (n > BUFFER_SIZE) {
n = BUFFER_SIZE;
}
buffer[n] = '';

// do something with buffer
int width = n;
printf("%dn", width);
if (width > 16) {
width = 16;
}
for (int i = 0; i < width; i++) {
printf("%02X", buffer[i]);
}
printf("n");
for (int i = 0; i < width; i++) {
printf("%-2c", buffer[i]);
}
printf("n");

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
$





share|improve this answer


























  • So just to clarify: You are casting the buffer pointer into a Go pointer to a byte array of size 1 << 30 (big but not the maximum, just a convenient shift size, and a constant) and then creating a slice of that imaginary buffer.

    – Zan Lynx
    Nov 28 '18 at 16:16











  • @ZanLynx: Exactly. "The length is part of the [Go] array's type; it must evaluate to a non-negative [compile-time] constant representable by a value of type int.": Array types, The Go Programming Language Specification. So we need some trickery. Array length constant 1 << 30 is a simple way of describing a very large Go byte array that is handled by 32-bit int implementations.

    – peterSO
    Nov 28 '18 at 16:30
















4












4








4







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]='';
int n = read_go(buffer, BUFFER_SIZE);
if (n < 0) {
printf("read_go: error: %dn", n);
n = 0;
}
if (n > BUFFER_SIZE) {
n = BUFFER_SIZE;
}
buffer[n] = '';

// do something with buffer
int width = n;
printf("%dn", width);
if (width > 16) {
width = 16;
}
for (int i = 0; i < width; i++) {
printf("%02X", buffer[i]);
}
printf("n");
for (int i = 0; i < width; i++) {
printf("%-2c", buffer[i]);
}
printf("n");

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
$





share|improve this answer















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]='';
int n = read_go(buffer, BUFFER_SIZE);
if (n < 0) {
printf("read_go: error: %dn", n);
n = 0;
}
if (n > BUFFER_SIZE) {
n = BUFFER_SIZE;
}
buffer[n] = '';

// do something with buffer
int width = n;
printf("%dn", width);
if (width > 16) {
width = 16;
}
for (int i = 0; i < width; i++) {
printf("%02X", buffer[i]);
}
printf("n");
for (int i = 0; i < width; i++) {
printf("%-2c", buffer[i]);
}
printf("n");

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
$






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 28 '18 at 16:44

























answered Nov 28 '18 at 15:33









peterSOpeterSO

98.2k15165182




98.2k15165182













  • So just to clarify: You are casting the buffer pointer into a Go pointer to a byte array of size 1 << 30 (big but not the maximum, just a convenient shift size, and a constant) and then creating a slice of that imaginary buffer.

    – Zan Lynx
    Nov 28 '18 at 16:16











  • @ZanLynx: Exactly. "The length is part of the [Go] array's type; it must evaluate to a non-negative [compile-time] constant representable by a value of type int.": Array types, The Go Programming Language Specification. So we need some trickery. Array length constant 1 << 30 is a simple way of describing a very large Go byte array that is handled by 32-bit int implementations.

    – peterSO
    Nov 28 '18 at 16:30





















  • So just to clarify: You are casting the buffer pointer into a Go pointer to a byte array of size 1 << 30 (big but not the maximum, just a convenient shift size, and a constant) and then creating a slice of that imaginary buffer.

    – Zan Lynx
    Nov 28 '18 at 16:16











  • @ZanLynx: Exactly. "The length is part of the [Go] array's type; it must evaluate to a non-negative [compile-time] constant representable by a value of type int.": Array types, The Go Programming Language Specification. So we need some trickery. Array length constant 1 << 30 is a simple way of describing a very large Go byte array that is handled by 32-bit int implementations.

    – peterSO
    Nov 28 '18 at 16:30



















So just to clarify: You are casting the buffer pointer into a Go pointer to a byte array of size 1 << 30 (big but not the maximum, just a convenient shift size, and a constant) and then creating a slice of that imaginary buffer.

– Zan Lynx
Nov 28 '18 at 16:16





So just to clarify: You are casting the buffer pointer into a Go pointer to a byte array of size 1 << 30 (big but not the maximum, just a convenient shift size, and a constant) and then creating a slice of that imaginary buffer.

– Zan Lynx
Nov 28 '18 at 16:16













@ZanLynx: Exactly. "The length is part of the [Go] array's type; it must evaluate to a non-negative [compile-time] constant representable by a value of type int.": Array types, The Go Programming Language Specification. So we need some trickery. Array length constant 1 << 30 is a simple way of describing a very large Go byte array that is handled by 32-bit int implementations.

– peterSO
Nov 28 '18 at 16:30







@ZanLynx: Exactly. "The length is part of the [Go] array's type; it must evaluate to a non-negative [compile-time] constant representable by a value of type int.": Array types, The Go Programming Language Specification. So we need some trickery. Array length constant 1 << 30 is a simple way of describing a very large Go byte array that is handled by 32-bit int implementations.

– peterSO
Nov 28 '18 at 16:30






















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53511478%2fis-it-safe-to-convert-c-uint8-t-to-uint8%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Lallio

Unable to find Lightning Node

Futebolista