Everything is working just fine if a string object is constructed from a static string constant or by means of constants concatenation. An exception occurs during program runtime if a string is a result of other objects combination.
mystr := “test string” C.Test(unsafe.Pointer(&mystr)) // works
mystr1 := "test " + "string" C.Test(unsafe.Pointer(&mystr1)) // works stradd := "string" mystr2 := "test " + stradd // Op3 C.Test(unsafe.Pointer(&mystr2)) // does not work
Console output after program execution:
panic: runtime error: cgo argument has Go pointer to Go pointer goroutine 1 [running]: received: test string received: test string panic(0x464780, 0xc04204a080) C:/Go/src/runtime/panic.go:500 +0x1af main._cgoCheckPointer0(0xc04204a050, 0xc04204a070, 0x1, 0x1, 0xc04204a06b) _/c_/examples/gostring/gostring/_obj/_cgo_gotypes.go:35 +0x60 main.main() c:/examples/gostring/gostring/gostring.go:20 +0x2ae
It’s not clear where the cgoCheckPointer0 detects a pointer to a pointer. Perhaps this will be fixed in the next versions. It is also possible that a method of outwitting the cgoCheckPointer0 (please see below) will also stop working.
Solution
So, we will try to eliminate checks as such in order to avoid exclusions via converting a pointer to an integer (uintptr):
package main /* typedef unsigned long long ULongLong; extern void Test1(ULongLong l); */ import "C" import "unsafe" func main() { v1 := "test " v2 := "test 2" str := v1 + v2 t := uintptr(unsafe.Pointer(&str)) C.Test1(C.ULongLong(t)) }
Function code in C in this case is:
#include <_cgo_export.h> #include <string.h> #include <stdio.h> typedef unsigned long long ULongLong; void Test1(ULongLong v) { GoString* gs = (GoString*)v; char buf[64]; int n = gs->n < sizeof(buf) - 1 ? gs->n : sizeof(buf) - 1; strncpy(buf, gs->p, n); buf[n] = '\0'; printf("received: %s\n", buf); }
Conclusion
The program works when you start it. This indicates that the data structure, which contains str string, does not differ from what is used for storage of static string constants and their concatenation – this is still the same GoString that we discussed in Part 1.
received: test test 2