2

次のように定義された構造体を持つ CGo パッケージがあるとします。

package test
...
type Test struct {
    Field *C.C_Test
}
...

ここで、別の場所から、 C 構造unsafe.Pointerを指していることがわかっているものを取得したとします。C_Test

以外のパッケージにある場合、値から新しいインスタンスを作成する方法はまったくないことを正しく理解していますか?test.Testunsafe.Pointertest

のようなものを使用しようとすると&test.Test{ptr}、フィールド値にメッセージが表示され、明らかな理由で失敗します。また、この型はエクスポートされないため、型変換ptrunsafe.Pointerうまくいきません。 そして、他のモジュールで CGo を使用するようにし、その中で同じ C 構造を再定義することも機能しないと思います。なぜなら、そのパッケージには のようなものがありますが必要であり、それらはタイプチェッカーの観点とは異なるからです。cannot use ptr (type unsafe.Pointer) as type *test._Ctype_C_Test*test._Ctype_C_Test
client._Ctype_C_Testtest.Testtest._Ctype_C_Test

いくつかの背景:ライブラリで使用GtkBuilderするときに、そのような構造を作成する方法が必要です。 そのメソッドは、構造体などに変換する必要があるフィールドを含むポインターを返します。それ自体には、 typeの明示的なフィールドを持つtype の暗黙的なフィールドが含まれているため、 に変換する必要がありますが、上記の簡単な例で説明したように変換できません。go-gtk
GtkBuilder.GetObject(name)*GObjectunsafe.Pointergtk.GtkEntrygtk.GtkEntrygtk.GtkWidget*C.GtkWidgetunsafe.Pointer*C.GtkWidget

更新:これが私が強制的に動作させようとしているコードです: https://gist.github.com/4141343

4

2 に答える 2

3

私はゴランナッツについて質問し、私がやりたいことをする方法の例を与えられました。今はうまくいくようです。イアンの答えからのコードは次のとおりです。

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

したがって、必要なのは、にunsafe.Pointer、次ににダブルキャストすることだけ*unsafe.Pointerです。割り当てプロセスを簡素化するために、次のコードを思いつきました。

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{}
    Assign(unsafe.Pointer(&messageNameEntryWidget.Widget),
           unsafe.Pointer(&builder.GetObject("messageNameEntry").Object))
}

しかし、このようなトリックを行うのは苦痛なので、GTKの使用を控えることにしましたが、これは質問とは関係ありません。

于 2012-11-29T19:42:23.920 に答える
2

のようなものでした

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

もテストされましたか?私はそれがうまくいくことを期待しています。(そう願っています。ちょっと。)

EDIT 2012-11-24 13:42 UTC: 2 回目の試行

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))}
        C.test_dump(test.Field)
}

$ go clean && go build && ls
main.go  13535422
$ ./13535422 
.foo 42, .bar Hello
$ 
于 2012-11-23T21:05:11.723 に答える