为了账号安全,请及时绑定邮箱和手机立即绑定

Go类型转换和未导出的CGo类型

Go类型转换和未导出的CGo类型

Go
森栏 2021-05-14 18:58:02
假设有一个CGo包,其结构定义如下:package test...type Test struct {    Field *C.C_Test}...现在假设我从其他地方得到unsafe.Pointer了我所知道的指向C_TestC结构的信息。我是否正确理解,有完全没有办法创造新的test.Test从实例unsafe.Pointer值,而在一个包被其他比test?尝试使用类似&test.Test{ptr},这里ptr是unsafe.Pointer价值,未能与消息显而易见的原因,cannot use ptr (type unsafe.Pointer) as type *test._Ctype_C_Test在字段值,以及类型转换到*test._Ctype_C_Test不工作,以及因为这种类型不出口。而且我认为,使我的其他模块使用CGo并在其中重新定义相同的C结构将不起作用,因为该程序包将具有类似client._Ctype_C_Test但test.Test需要的东西test._Ctype_C_Test,并且从类型检查器的角度来看是不同的。背景知识:在GtkBuilder与go-gtk库一起使用时,我需要一种创建这种结构的方法。它的GtkBuilder.GetObject(name)方法返回*GObject指针,该指针又包含unsafe.Pointer我需要以某种方式转换为gtk.GtkEntrystruct的字段。gtk.GtkEntry本身包含类型的隐式字段,该类型的隐式字段具有类型的gtk.GtkWidget显式字段*C.GtkWidget,因此我需要转换unsafe.Pointer为*C.GtkWidget,但是我不能转换,正如我在上面的简单示例中所述。更新:这是我要强制使用的代码:https : //gist.github.com/4141343
查看完整描述

2 回答

?
侃侃尔雅

TA贡献1801条经验 获得超16个赞

我问了一个关于golang-nuts的问题,并举例说明了如何做我想做的事情。现在似乎可以正常工作了。这是Ian的答案中的代码:


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,因为这样做很麻烦(),但这与问题无关。


查看完整回答
反对 回复 2021-05-24
?
人到中年有点甜

TA贡献1895条经验 获得超7个赞

有点像


foo := test.Test{}

*(unsafe.Pointer)(&foo.Field) = ptr

还测试过吗?我希望它能奏效。(希望如此。金田。)


编辑2012-11-24 13:42 UTC:第二次尝试


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


查看完整回答
反对 回复 2021-05-24
  • 2 回答
  • 0 关注
  • 287 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信