Reputation: 9893
I am calling golang
with c
, I want to return a string array
and a int array
, I do it like this:
package main
import "C"
//export Seg
func Seg(input *C.char, segs *[]*C.char, tags *[]int) (errChars *C.char) {
count := 10
segs_ := make([]*C.char, 10, 10)
for i:=0; i<count; i++ {
segs_[i] = C.CString("aaaaaa")
}
segs = &segs_
tags_ := make([]int, count)
for i:=0; i<count; i++ {
tags_[i] = i
}
tags = &tags_
return
}
func main() {}
Build with
go build -o libacrf.so -buildmode=c-shared clib.go
call it like this:
#include <stdio.h>
#include <stdlib.h>
#include "libacrf.h"
int main(int argc, char *argv[])
{
GoSlice *segs, *tags;
char* err;
err = Seg("hahahhaha", segs, tags);
if (err != NULL) {
fprintf(stderr, "error: %s\n", err);
free(err);
return 1;
}
printf("%llu\n", (*tags).len); // it should be 10, but it is not right now
return 0;
}
But the problem is that I can not get the real result from golang.
Upvotes: 0
Views: 1865
Reputation: 109318
This doesn't have anything to do with C, you're overwriting copies of the tags
and segs
pointer values, rather than assigning the new slice values; . Make an example in Go first so see exactly what you're doing. https://play.golang.org/p/EQWRiqVwqm
In order to assign the _tags
value to the pointer, the syntax should be
*tags = _tags
Upvotes: 2
Reputation: 176
I think it's because you are responsible for memory management for all C-side data.
In C GoSlice
is just typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
and in your example you pass just uninitialized pointer to GoSlice:
GoSlice *segs, *tags; //here
char* err;
err = Seg("hahahhaha", segs, tags);
So it's just pure luck that you can r/w at this memory location. While Go will not manage your memory chunks from c code it will also not set len field. While all above are just assumptions (i do not know a lot about Go) Some evidence supporting my hypothesis will be this modification:
int main(int argc, char *argv[])
{
GoInt data[10] = {77, 12, 5, 99, 28, 23, 33,33,33,33};
GoSlice segs_d = {data, 10, 10};
GoInt data2[10] = {77, 12, 5, 99, 28, 23, 33,33,33,33};
GoSlice tags_d = {data2, 10, 10};
GoSlice *segs, *tags;
segs= &segs_d;
tags= &tags_d;
char* err;
err = Seg("hahahhaha", segs, tags);
if (err != NULL) {
fprintf(stderr, "error: %s\n", err);
free(err);
return 1;
}
printf("%llu\n", (*tags).len); // it should be 10, but it is not right now
return 0;
}
Upvotes: 0