Is it safe to convert *C.uint8_t to []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?
c go cgo
add a comment |
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
It's always unsafe, as indicated by the use of theunsafepackage, but you still need to use it to convert types from C. You have thebufferSizevalue 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 functionreadis going to conflict with the system C library. Yours will take priority but other code that wants toreadthings 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 don, _ := 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
add a comment |
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
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
c go cgo
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 theunsafepackage, but you still need to use it to convert types from C. You have thebufferSizevalue 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 functionreadis going to conflict with the system C library. Yours will take priority but other code that wants toreadthings 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 don, _ := 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
add a comment |
It's always unsafe, as indicated by the use of theunsafepackage, but you still need to use it to convert types from C. You have thebufferSizevalue 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 functionreadis going to conflict with the system C library. Yours will take priority but other code that wants toreadthings 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 don, _ := 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
add a comment |
1 Answer
1
active
oldest
votes
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
$
So just to clarify: You are casting thebufferpointer into a Go pointer to a byte array of size1 << 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 constant1 << 30is a simple way of describing a very large Gobytearray that is handled by 32-bitintimplementations.
– peterSO
Nov 28 '18 at 16:30
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
$
So just to clarify: You are casting thebufferpointer into a Go pointer to a byte array of size1 << 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 constant1 << 30is a simple way of describing a very large Gobytearray that is handled by 32-bitintimplementations.
– peterSO
Nov 28 '18 at 16:30
add a comment |
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
$
So just to clarify: You are casting thebufferpointer into a Go pointer to a byte array of size1 << 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 constant1 << 30is a simple way of describing a very large Gobytearray that is handled by 32-bitintimplementations.
– peterSO
Nov 28 '18 at 16:30
add a comment |
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
$
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
$
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 thebufferpointer into a Go pointer to a byte array of size1 << 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 constant1 << 30is a simple way of describing a very large Gobytearray that is handled by 32-bitintimplementations.
– peterSO
Nov 28 '18 at 16:30
add a comment |
So just to clarify: You are casting thebufferpointer into a Go pointer to a byte array of size1 << 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 constant1 << 30is a simple way of describing a very large Gobytearray that is handled by 32-bitintimplementations.
– 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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
It's always unsafe, as indicated by the use of the
unsafepackage, but you still need to use it to convert types from C. You have thebufferSizevalue 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
readis going to conflict with the system C library. Yours will take priority but other code that wants toreadthings 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