Take the 2-minute tour ×

Suppose there is CGo package with a struct defined like this:

package test
type Test struct {
    Field *C.C_Test

Now suppose that from somewhere else I get unsafe.Pointer which I know points to C_Test C structure.

Do I understand correctly that there is completely no way to create new test.Test instance from the unsafe.Pointer value while being in a package other than test?

Attempting to use something like &test.Test{ptr}, where ptr is unsafe.Pointer value, fails for obvious reasons with message cannot use ptr (type unsafe.Pointer) as type *test._Ctype_C_Test in field value, and type conversion to *test._Ctype_C_Test does not work as well because this type is not exported.
And I think that making my other module to use CGo and redefining the same C structure in it will not work either since that package will have something like client._Ctype_C_Test but test.Test requires test._Ctype_C_Test, and they are different from the point of view of the typechecker.

Some background: I need a way to create such structure when I use GtkBuilder with go-gtk library.
Its GtkBuilder.GetObject(name) method returns *GObject pointer which in turn contains unsafe.Pointer field which I need to turn somehow into, say, gtk.GtkEntry struct. gtk.GtkEntry itself contains implicit field of type gtk.GtkWidget which has explicit field of type *C.GtkWidget, so I need to convert unsafe.Pointer to *C.GtkWidget, but I cannot, as I have described in the simple example above.

Update: here is the code I'm trying to force to work: https://gist.github.com/4141343

share|improve this question
add comment

2 Answers

Was something like

foo := test.Test{}
*(unsafe.Pointer)(&foo.Field) = ptr

also tested? I would expect that to work. (Hope so. Kinda.)

EDIT 2012-11-24 13:42 UTC: 2nd attempt

package main


#include <stdio.h>
#include <stdlib.h>

typedef struct {
        int foo;
        char *bar;
} Test_t;

void test_dump(Test_t *test) {
        printf(".foo %d, .bar %s\n", test->foo, test->bar);

void *test_new(int foo, char *bar) {
        Test_t *p = malloc(sizeof(Test_t));
        p->foo = foo;
        p->bar = bar;
        return p;

import "C"

import "unsafe"

type Test struct {
        Field *C.Test_t

func main() {
        hello := C.CString("Hello")
        defer C.free(unsafe.Pointer(hello))
        test := &Test{(*C.Test_t)(C.test_new(42, hello))}

$ go clean && go build && ls
main.go  13535422
$ ./13535422 
.foo 42, .bar Hello
share|improve this answer
No, unfortunately, this does not work. I'm getting invalid indirect of unsafe.Pointer(&foo.Field) (type unsafe.Pointer) in terms of example. –  Vladimir Matveev Nov 24 '12 at 9:09
Would like to see the code. Anyway, editing the answer now... –  zzzz Nov 24 '12 at 13:41
Yes, your code will work, because C structure definition is in the same package as the unsafe pointer conversion attempt. I wrote about this in my answer. Try moving main function in separate package and you will see what I mean. I will add example code shortly. –  Vladimir Matveev Nov 24 '12 at 20:39
Sorry, I meant 'question' instead of 'answer' :) –  Vladimir Matveev Nov 24 '12 at 20:55
add comment
up vote 1 down vote accepted

I asked a question on golang-nuts and was given an example on how to do what I want. It seems to work now. Here is the code from Ian's answer:

var t test.Test
p := (*unsafe.Pointer)(unsafe.Pointer(&t.Field))
*p = unsafe.Pointer(u)

So, all what was needed is double cast to unsafe.Pointer and then to *unsafe.Pointer. I came up with the following code to simplify the assign process:

func Assign(to unsafe.Pointer, from unsafe.Pointer) {
    fptr := (*unsafe.Pointer)(from)
    tptr := (*unsafe.Pointer)(to)
    *tptr = *fptr

func Init(builder *gtk.GtkBuilder) {
    messageNameEntryWidget := gtk.GtkWidget{}

Then, however, I decided to abstain from using GTK, since it is painful to do tricks like this) but this is not related to the question.

share|improve this answer
add comment

Your Answer


