Hi, Ian, Sorry about the confusion! My gocode set the value of the device and then pass it to C++ code.
Code goes like this: device := "eth1" // hardcoding this value works or retrieving it from Flag as below flag.StringVar(&device, "Device", "eth1", "NIC to Listen") ------- lines below do not change ------------ itc := device // with or without this. libpi.PI_init_global_config(1, &itc) func PI_init_global_config(arg1 int, arg2 *string) { _swig_i_0 := arg1 _swig_i_1 := arg2 C._wrap_PI_init_global_config_libpi_de8cf075b4f6dbec(C.swig_intgo(_swig_i_0), C.swig_voidp(_swig_i_1)) } void _wrap_PI_init_global_config_libpi_de8cf075b4f6dbec(intgo _swig_go_0, _gostring_* _swig_go_1) { int arg1 ; char **arg2 ; arg1 = (int)_swig_go_0; arg2 = *(char ***)&_swig_go_1; PI_init_global_config(arg1,arg2); } Then eventually to the C++ library with function header defined as void PI_init_global_config(int argc, char *argv[]); ----------------------------------------------------------- If I am trying to retrieve the value of var device from a json file, such as file, err := os.Open("config.json") if err != nil { return } defer file.Close() decoder1 := json.NewDecoder(file) conf := &Configuration{} err = decoder1.Decode(conf) fmt.Println("conf is ", conf) // the print shows that I get eth1 if err != nil { return } device = conf.device //fmt.println gives eth1 or device = fmt.Sprintf("%s", conf.Device) The code always crashes with the go pointer error. I just don't understand what is the difference between hardcoding the value and retrieving it from the json file. Can you please help me to understand it? Thanks, Chun On Monday, November 6, 2017 at 1:44:54 PM UTC-5, Ian Lance Taylor wrote: > > On Mon, Nov 6, 2017 at 10:29 AM, Chun Zhang <chun...@gmail.com > <javascript:>> wrote: > > Thank you Ian!! That does make sense. > > > > Can you please elaborate why hardcoding device = "eth1" works? What is > the > > difference here? > > I'm sorry, I'm not sure I really understand the question. The pointer > passing rules apply only when calling functions written in C rather > than Go. When you write `device = "eth1"` there is no C function > involved. > > Ian > > > On Mon, Nov 6, 2017 at 1:19 PM, Ian Lance Taylor <ia...@golang.org > <javascript:>> wrote: > >> > >> On Mon, Nov 6, 2017 at 4:25 AM, Chun Zhang <chun...@gmail.com > <javascript:>> wrote: > >> > > >> > Thank you for the reply! > >> > > >> > The C libi.PI_init_global_config has the interface of > >> > PI_init_global_config(int argc, char *argv[]); > >> > so Swig converts it to PI_init_global_config(arg1 int, arg2 *string) > >> > > >> > The code was expecting to a *string. Viper.GetString returns a string > as > >> > far > >> > as I can see, is that right? So device is a string, not a *string. > >> > (verified > >> > with reflect.TypeOf). Everything matches except for the crash :( > >> > > >> > What really puzzles me is that why when passing the parameter using > flag > >> > is > >> > fine, as well as when hard-coding the value. In both cases, device is > >> > still > >> > a string, nothing changed. But whenever trying to read the value from > a > >> > config file using viper or just simple json.decoder, the code > complains > >> > it > >> > is a pointer to a pointer. I mean, I literally did a comparison > between > >> > the > >> > read-in value and a variable hard-coded as "eth1", it says they are > >> > equal. > >> > >> A Go string contains an internal pointer. Passing a *string to cgo > >> means that you are passing a pointer to a string that contains a > >> pointer, so you are passing a pointer to a pointer. That is invalid > >> according to the cgo pointer passing rules. > >> > >> A Go string is definitely not a C or C++ string. You can not pass a > >> pointer to a Go string to C code that expects a char**. Even if cgo > >> permitted it, it would not work. If SWIG is converting a C char** (or > >> char*[]) to Go *string, then SWIG is getting it wrong. > >> > >> Ian > >> > >> > >> > On Monday, November 6, 2017 at 1:07:46 AM UTC-5, Tamás Gulácsi wrote: > >> >> > >> >> > >> >> 2017. november 6., hétfő 2:11:48 UTC+1 időpontban Chun Zhang a > >> >> következőt > >> >> írta: > >> >>> > >> >>> Hi, All, > >> >>> > >> >>> I am trying to read a configuration file using Viper, the config > file > >> >>> is > >> >>> a very simple json file with one line > >> >>> { > >> >>> "device" : "eth1" > >> >>> } > >> >>> > >> >>> I use the following line to read it > >> >>> > >> >>> device := viper.GetString("device") > >> >>> > >> >>> > >> >>> then passing this var further into a C library with swig generated > api > >> >>> as > >> >>> arg2 > >> >>> > >> >>> itc := device //Need to update if there is more devices > >> >>> libpi.PI_init_global_config(1, &itc) > >> >>> > >> >>> func PI_init_global_config(arg1 int, arg2 *string) { > >> >>> > >> >>> > >> >>> > >> >>> I can retrieve the correct value, and can verify that var device > does > >> >>> have eth1 as the value when printf it. I even did the compare of > >> >>> device == > >> >>> "eth1", and the result is true. > >> >>> > >> >>> However, when passing this device var to the PI_init_gloable_config > >> >>> API, > >> >>> I got code crashed with the following error > >> >>> > >> >>> panic: runtime error: cgo argument has Go pointer to Go pointer > >> >>> > >> >> > >> >> > >> >> The value you pass to C must not have a pointer which points to a Go > >> >> pointer. > >> >> What are you passing to libpi.PI_init_global_config ? > >> >> I think "device" is already a *string, so &itc is a **string - try > >> >> libpi.PI_init_global_config(device). > >> >> > >> >> (I assume libpi does some conversion, as the proper way to pass a > >> >> string > >> >> ot C (*char) is to convert the string to *char with > >> >> cs:=C.CString(*device) > >> >> and later C.free(unsafe.Pointer(cs)) it). > >> >>> > >> >>> > >> >>> If instead of reading this file from configuration json, I hardcode > it > >> >>> in > >> >>> the code as > >> >>> > >> >>> device := "eth1" > >> >>> > >> >>> then there is no issue at all. If I read this variable using Flag > from > >> >>> command line, like > >> >>> > >> >>> flag.StringVar(&device, "Device", "eth1", "NIC to Listen") > >> >>> > >> >>> > >> >>> there was no problem either. > >> >>> > >> >>> > >> >>> > >> >>> Can anybody please enlighten me what's the difference? Why this > error > >> >>> is > >> >>> triggered? I googled quite a bit, but it does not seem to help. I > have > >> >>> go > >> >>> 1.8.3 installed. > >> >>> > >> >>> Thanks, > >> >>> Chun > >> > > >> > -- > >> > You received this message because you are subscribed to the Google > >> > Groups > >> > "golang-nuts" group. > >> > To unsubscribe from this group and stop receiving emails from it, > send > >> > an > >> > email to golang-nuts...@googlegroups.com <javascript:>. > >> > For more options, visit https://groups.google.com/d/optout. > > > > > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.