I have a C function that returns NULL when an exception occurs. How can I check whether the returned value is NULL or not in Go since it has no built-in types to represent C NULL. Below is my code
retVal := C.myfunc()
if retVal == nil {
// handle the error
}
I think you can use nil to test if the c function returns NULL. Try the following code:
package main
/*
#include <stdio.h>
#include <stdlib.h>
int* cfunc(int i) {
if (i == 0) {
return NULL;
}
int *p = (int*)malloc(sizeof(int));
*p = 100;
return p;
}
*/
import "C"
import "fmt"
import "unsafe"
func call_cfunc(i int32) {
ret := C.cfunc(C.int(i))
if ret == nil {
fmt.Println("nil")
} else {
fmt.Println(*ret)
C.free(unsafe.Pointer(ret))
}
}
func main() {
call_cfunc(0)
call_cfunc(1)
}
Related
So I am trying to implement my own linked list in Go. I believe I have everything correct, but can't check because it's not complete yet. The structs and interfaces were given to me, so they HAVE to be correct. The functions are all my work. Any help regarding the Next and begin functions would be greatly appreciated. it appears I can't return the *it in the next function.
package main
import (
"fmt"
)
type Vector struct {
num [] interface{}
size int
}
type VectorIterator struct {
x Vector
i int
}
type List struct {
l *ListIterator
}
type ListIterator struct {
num interface{}
next *ListIterator
}
type Container interface {
begin() Iterator
append (v interface{})
}
type Iterator interface {
next() Iterator
isEnd() bool
Deref () interface {}
}
func (it *ListIterator) isEnd() bool {
if it.next == nil {
return true
} else {
return false
}
}
func (it *VectorIterator) isEnd() bool {
if it.Next() == nil {
return true
} else {
return false
}
}
func (it *ListIterator) Deref() interface {} {
return it.num
}
func (it *ListIterator) append(v interface{}) {
for {
it.Next()
if it.isEnd() == true {
break
}
}
it.Next()
it.num = v
}
func (it *ListIterator) begin() Iterator {
}
func (it *ListIterator) Next() Iterator {
if it.isEnd() == false {
it = it.next
}
return *it
}
Why both these destroy functions do not change pointer to nil and how can I create such function?
package main
import (
"fmt"
)
type position struct {
x int
y int
}
func (p *position) destroy() {
p = nil
}
func destroy(p *position) {
p = nil
}
func main() {
p1 := &position{1,1}
p2 := &position{2,2}
p1.destroy()
destroy(p2)
if p1 == nil {
fmt.Println("p1 == nil")
} else {
fmt.Println(p1)
}
if p2 == nil {
fmt.Println("p2 == nil")
} else {
fmt.Println(p2)
}
}
Outputs:
&{1 1}
&{2 2}
https://play.golang.org/p/BmZjX1Hw24u
You need a pointer to pointer to change a pointer's value.
Here's your code sample, modified to do this (playground):
package main
import (
"fmt"
)
type position struct {
x int
y int
}
func destroy(p **position) {
*p = nil
}
func main() {
p1 := &position{1, 1}
destroy(&p1)
if p1 == nil {
fmt.Println("p1 == nil")
} else {
fmt.Println(p1)
}
}
In your current code
func destroy(p *position) {
p = nil
}
Inside destroy, p is a value the holds the address of a position struct. By assigning something to p itself, you're simply making it hold the address of some other position struct (or nil). You're not modifying the original pointer passed in.
This isn't different from a function trying to modify its argument by assigning to it:
// This will not actually modify the argument passed in by the caller
func setto2(value int) {
value = 2
}
The go spec says, in the section about calls and call parameters:
After they are evaluated, the parameters of the call are passed by
value to the function and the called function begins execution. The
return parameters of the function are passed by value back to the
calling function when the function returns.
I want to pass the pointer to the first element of a slice []float32 to a C variable, but somehow I can't figure out how.
C Code:
typedef struct
{ const float *data_in ;
float *data_out ;
} SRC_DATA ;
Go:
mySlice := make([]float32, 20)
foo := C.SRC_DATA{}
foo.data_in = *C.float(&mySlice[0]) // here the program breaks
As far as I have understood, it should be possible to pass directly a pointer to the first element in the slice from Go to C, without using unsafe.Pointer().
The C function will then iterate over the slice (length known).
Any hints are appreciated!
You need to use a slice of C.float type instead of float32:
package main
/*
#include <stdio.h>
void test(float *in) {
printf("C %f %f\n", in[0], in[1]);
}
*/
import "C"
func main() {
in := []C.float{1.23, 4.56}
C.test(&in[0]) // C 1.230000 4.560000
}
Go doesn't allow to store a Go pointer in a Go allocated structure passed to Cgo:
package main
/*
#include <stdio.h>
typedef struct {
float *in;
float *out;
} SRC_DATA;
void test(SRC_DATA *data) {
printf("C %f %f\n", data->in[0], data->in[1]);
data->out[0] = 8.8;
data->out[1] = 9.9;
}
*/
import "C"
import "fmt"
func main() {
in := []C.float{1.23, 4.56}
out := make([]C.float, 2)
data := &C.SRC_DATA{in: &in[0], out: &out[0]}
C.test(data) // panic: runtime error: cgo argument has Go pointer to Go pointer
fmt.Println("Go", out)
}
But you can create a helper function in C:
package main
/*
#include <stdio.h>
typedef struct {
float *in;
float *out;
} SRC_DATA;
void test(SRC_DATA *data) {
printf("C %f %f\n", data->in[0], data->in[1]);
data->out[0] = 8.8;
data->out[1] = 9.9;
}
void test_helper(float *in, float *out) {
SRC_DATA data;
data.in = in;
data.out = out;
test(&data);
}
*/
import "C"
import "fmt"
func main() {
in := []C.float{1.23, 4.56}
out := make([]C.float, 2)
C.test_helper(&in[0], &out[0]) // C 1.230000 4.560000
fmt.Println("Go", out) // Go [8.8 9.9]
}
Alternatively you can allocate and free SRC_DATA structure in C:
package main
/*
#include <stdio.h>
#include <stdlib.h>
typedef struct {
float *in;
float *out;
} SRC_DATA;
void test(SRC_DATA *data) {
printf("C %f %f\n", data->in[0], data->in[1]);
data->out[0] = 8.8;
data->out[1] = 9.9;
}
SRC_DATA *alloc_src_data() {
return (SRC_DATA*)malloc(sizeof(SRC_DATA));
}
void free_src_data(SRC_DATA *p) {
free(p);
}
*/
import "C"
import "fmt"
func main() {
in := []C.float{1.23, 4.56}
out := make([]C.float, 2)
data := C.alloc_src_data()
defer C.free_src_data(data)
data.in = &in[0]
data.out = &out[0]
C.test(data) // C 1.230000 4.560000
fmt.Println("Go", out) // Go [8.8 9.9]
}
I can define a function globally,
func f()int{
return 0
}
But I can also do in main,
func main(){
var f=func()int{
return 0
}
}
Can I do the same with receiving methods? I can do globally,
type I int
func(i I)f()int{
return int(i)
}
But can I do this in main too, so like (because this does not work)
func main(){
type I int
var f=func(i I)()int{
return 0
}
}
No, not like that,
but like this working sample code you may still use f:
package main
import "fmt"
func main() {
j := I(2)
fmt.Println(j.Double())
f := j.Double
fmt.Println(f())
}
type I int
func (i I) Double() int {
return int(i) * 2
}
output:
4
4
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
How does golang share or read other processes shared memory?
I've checked some information, but did not find relevant information. Can anyone give me an example?
In the world of go, don't communicate by sharing memory; share memory by communicating. If you really want to have a try, you can call the C API with cgo:
wrapper.c:
#include <stdlib.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/types.h>
int my_shm_open(char* filename, int open_flag){
int shm_id;
key_t key;
key = ftok(filename, 0x03);
if(key == -1){
return -1;
}
if(open_flag)
shm_id = shmget(key, 4096, IPC_CREAT|IPC_EXCL|0600);
else
shm_id = shmget(key, 0, 0);
if(shm_id == -1){
return -1;
}
return shm_id;
}
int my_shm_update(int shm_id, char* content){
char* addr;
addr = (char*)shmat(shm_id, NULL, 0);
if(addr == (char*)-1){
return -1;
}
if(strlen(content) > 4095)
return -1;
strcpy(addr, content);
shmdt(addr);
return 0;
}
int my_shm_close(int shm_id){
shmctl(shm_id, IPC_RMID, NULL);
return 0;
}
char* my_shm_read(char* filename){
int shm_id;
char* addr;
char* s;
shm_id = my_shm_open(filename, 0);
if(shm_id == -1)
return NULL;
addr = (char*)shmat(shm_id, NULL, 0);
if(addr == (char*)-1){
return NULL;
}
s = (char*)malloc(strlen(addr) + 1);
strcpy(s, addr);
shmdt(addr);
return s;
}
reader.go
package main
// #include <stdlib.h>
// #include "wrapper.c"
import "C"
import "unsafe"
import "fmt"
func read(filename string) string {
f := C.CString(filename)
defer C.free(unsafe.Pointer(f))
s := C.my_shm_read(f)
defer C.free(unsafe.Pointer(s))
return C.GoString(s)
}
func main() {
fmt.Println(read("/tmp"))
}
writter.go:
package main
// #include <stdlib.h>
// #include "wrapper.c"
import "C"
import "unsafe"
import (
"log"
"time"
)
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
func open(file string) (int, error) {
f := C.CString(file)
defer C.free(unsafe.Pointer(f))
r := int(C.my_shm_open(f, C.int(1)))
if r == -1 {
return 0, &errorString{"error"}
}
return r, nil
}
func update(shm_id int, content string) error {
c := C.CString(content)
defer C.free(unsafe.Pointer(c))
r := int(C.my_shm_update(C.int(shm_id), c))
if r == -1 {
return &errorString{"update error"}
}
return nil
}
func close(shm_id int) error {
C.my_shm_close(C.int(shm_id))
return nil
}
func main() {
id, err := open("/tmp")
if err != nil {
log.Fatal(err)
}
defer close(id)
err = update(id, "hello world")
if err != nil {
log.Fatal(err)
}
time.Sleep(1e9 * 100)
}
run the writer, then the reader by go run filename.
The code is from here
golang: It is a programming language, so it does not relate to the shared memory that the operating system level things. Not to say golang not use shared memory, but this is not it need to be defined. Posix use shared memory, you can use syscall package, which contains a lot of system calls, as long as the reference c system call interface on the line.