当前位置: 首页 > 知识库问答 >
问题:

从C到Golang获取结构

田远
2023-03-14

c.h

typedef signed int VarInt32;

typedef struct {
    VarInt32   VI32
} VAR_A, *VAR_B

int Add(VAR_B v_b) //the argument is a pointer

var mvar unsafe.Pointer

C.Add((*C.VAR_B)(&mvar))

fmt.Println(mvar)

得到这样的结果:

warning: passing argument 1 of ‘add’ from incompatible pointer type [enabled by default]
note: expected ‘MVAR’ but argument is of type ‘struct <anonymous> *’

这似乎不正确,

我正在golang寻找类似的东西:mvar.VI32

谢谢

我的头很痛,不擅长C / C,

这是我的场景,调用一个SDK(带有.so库)

c.h

typedef char*   MPChar;
typedef MLong   MRESULT;

typedef struct{
    MPChar startTime;       
    MPChar endTime;         
    MPChar platform;        
    MPChar sdkType;         
    MPChar appId;           
    MPChar sdkKey;          
    MPChar sdkVersion;      
    MPChar fileVersion;     
}ASF_ActiveFileInfo, *LPASF_ActiveFileInfo;


MRESULT ASFGetActiveFileInfo(
    LPASF_ActiveFileInfo  activeFileInfo 
);

我试着用Go语言调用函数ASFGetActiveFileInfo,如下所示:

var c_afInfo C.ASF_ActiveFileInfo

C.ASFGetActiveFileInfo(&c_afInfo)

//get the same error
//C.ASFGetActiveFileInfo((C.LPASF_ActiveFileInfo)(unsafe.Pointer(&c_afInfo)))

得到这个错误:

# command-line-arguments
cgo-gcc-prolog: In function ‘_cgo_8c613494cf5f_Cfunc_ASFGetActiveFileInfo’:
cgo-gcc-prolog:52:2: warning: passing argument 1 of ‘ASFGetActiveFileInfo’ from incompatible pointer type [enabled by default]
In file included from ./main.go:7:0:
./inc/arcsoft_face_sdk.h:104:9: note: expected ‘LPASF_ActiveFileInfo’ but argument is of type ‘struct <anonymous> *’
 MRESULT ASFGetActiveFileInfo(
         ^
# command-line-arguments
./main.go:134:139: cannot use _cgo0 (type *_Ctype_LPASF_ActiveFileInfo) as type *_Ctype_struct___0 in argument to _Cfunc_ASFGetActiveFileInfo

尝试:

var c_afInfo C.LPASF_ActiveFileInfo

C.ASFGetActiveFileInfo((C.LPASF_ActiveFileInfo)&c_afInfo)

得到这个错误

# command-line-arguments
cgo-gcc-prolog: In function ‘_cgo_061c0167bf6c_Cfunc_ASFGetActiveFileInfo’:
cgo-gcc-prolog:52:2: warning: passing argument 1 of ‘ASFGetActiveFileInfo’ from incompatible pointer type [enabled by default]
In file included from ./main.go:7:0:
./inc/arcsoft_face_sdk.h:104:9: note: expected ‘LPASF_ActiveFileInfo’ but argument is of type ‘struct <anonymous> *’
 MRESULT ASFGetActiveFileInfo(
         ^
# command-line-arguments
./main.go:134:25: type _Ctype_LPASF_ActiveFileInfo is not an expression

这个问题有什么解决方案吗?

感谢@peterSO的回答,它工作,但仍然显示错误:

cgo-gcc-prolog: In function ‘_cgo_73061f0a5639_Cfunc_ASFGetActiveFileInfo’:
cgo-gcc-prolog:98:2: warning: passing argument 1 of ‘ASFGetActiveFileInfo’ from incompatible pointer type [enabled by default]
In file included from ./main.go:7:0:
./inc/arcsoft_face_sdk.h:104:9: note: expected ‘LPASF_ActiveFileInfo’ but argument is of type ‘struct <anonymous> *’
 MRESULT ASFGetActiveFileInfo(
         ^
0 linux


事实非常接近

演示:https://github.com/JoeZing/stackdemo

共有1个答案

杨豪
2023-03-14

围棋与 cgo 中所有晦涩难懂的 C 类型划分规则都不匹配。保持简单。

使用no struct标记示例,以下是一些将C struct变量和指针参数从Go传递到C Add函数的方法。它是不安全的,绕过了Go和C (GCC C编译器)检查。

package main

/*
// GNU Compiler Collection (GCC): Warning Options
// https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options
#cgo CFLAGS: -Wno-incompatible-pointer-types

typedef signed int i32_t;

// anonymous (no tag) struct
typedef struct {
    i32_t i;
} sv_t, *sp_t;

int Add(sv_t v, sp_t p);

int Add(sv_t v, sp_t p) {
    int sum = v.i;
    if (p) {
        sum += p->i;
    }
    return sum;
}
*/
import "C"

import (
    "fmt"
    "unsafe"
)

func main() {
    var svar C.sv_t
    svar.i = 42
    fmt.Printf("svar: %v  svar.i: %v\n", svar, svar.i)

    var sptr C.sp_t
    sptr = (C.sp_t)(unsafe.Pointer(new(C.sv_t)))
    sptr.i = 39
    fmt.Printf("sptr: %v  sptr.i: %v\n", sptr, sptr.i)

    sum := C.Add(svar, sptr)
    fmt.Print("Add(", svar.i, ", ", sptr.i, ") = ", sum, "\n")

    fmt.Printf("svar: %T\nsptr: %T\n", svar, sptr)
}

/*

输出:

$ go run so.go
svar: {42}  svar.i: 42
sptr: &{39}  sptr.i: 39
Add(42, 39) = 81
svar: main._Ctype_struct___0
sptr: main._Ctype_sp_t
$ 

对于您的具体示例,也许是这样的:

package main

/*
// GNU Compiler Collection (GCC): Warning Options
// https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options
#cgo CFLAGS: -Wno-incompatible-pointer-types

typedef long    MLong;
typedef char*   MPChar;
typedef MLong   MRESULT;

typedef struct {
    MPChar startTime;
    MPChar endTime;
    MPChar platform;
    MPChar sdkType;
    MPChar appId;
    MPChar sdkKey;
    MPChar sdkVersion;
    MPChar fileVersion;
} ASF_ActiveFileInfo, *LPASF_ActiveFileInfo;


MRESULT ASFGetActiveFileInfo(
    LPASF_ActiveFileInfo  activeFileInfo
);

MRESULT ASFGetActiveFileInfo(
    LPASF_ActiveFileInfo  activeFileInfo
)
{
    activeFileInfo->appId = "Go";
    return 42;
}
*/
import "C"

import (
    "fmt"
    "unsafe"
)

func main() {
    asfPtr := (C.LPASF_ActiveFileInfo)(unsafe.Pointer(new(C.ASF_ActiveFileInfo)))
    r := C.ASFGetActiveFileInfo(asfPtr)
    fmt.Println(r, C.GoString(asfPtr.appId))
}

输出:

$ go run so.go
42 Go
$ 

使用您的示例(使用<code>struct

package main

/*
typedef signed int i32_t;

typedef struct s_t {
    i32_t i;
} sv_t, *sp_t;

int Add(sv_t v, sp_t p);

int Add(sv_t v, sp_t p) {
    int sum = v.i;
    if (p) {
        sum += p->i;
    }
    return sum;
}
*/
import "C"

import (
    "fmt"
    "unsafe"
)

func main() {
    svar := C.struct_s_t{i: 42}

    sptr := &C.struct_s_t{i: 39}
    sum := C.Add(svar, sptr)
    fmt.Print("Add(", svar.i, ", ", sptr.i, ") = ", sum, "\n")

    uptr := unsafe.Pointer(&C.struct_s_t{i: 7})
    sum = C.Add(svar, (C.sp_t)(uptr))
    fmt.Print("Add(", svar.i, ", ", (C.sp_t)(uptr).i, ") = ", sum, "\n")
    sum = C.Add(svar, (*C.struct_s_t)(uptr))
    fmt.Print("Add(", svar.i, ", ", (*C.struct_s_t)(uptr).i, ") = ", sum, "\n")

    fmt.Printf("svar: %T\nsptr: %T\nuptr: %T\n", svar, sptr, uptr)
}

输出:

$ go run so.go
Add(42, 39) = 81
Add(42, 7) = 49
Add(42, 7) = 49
svar: main._Ctype_struct_s_t
sptr: *main._Ctype_struct_s_t
uptr: unsafe.Pointer
$
 类似资料:
  • 我试图通过C结构从主要Go语言代码到不同的包,并得到类型转换错误。 C头文件test.h 高浪包测试 Go语言主要代码 编译主代码时,我收到以下错误:无法转换 当我尝试对变量进行类型转换时,它给出了以下错误:无法引用未报告的名称测试_Ctype_struct_dd_err_struct无法转换 请帮我解决这个问题

  • 问题内容: 状态 在Linux上,从哪里获得“主机的根CA集”? 我需要知道这一点,以便能够全局添加另一个要信任的根CA。 问题答案: 它在以下位置搜索:https : //golang.org/src/crypto/x509/root_linux.go 摘抄

  • 我正在使用和Web API来执行某些任务,当任务完成时,API会在OK方法中返回一个对象。 代码: 如何在响应中获取此 blob 对象,我认为,这应该是 IHttp 操作结果? 任何帮助是值得赞赏的!

  • 问题内容: 我有一个json文本,我想获取作者姓名和描述标签的值。不需要其他字段,例如url和urltoimage等。当我运行以下代码时,不提供任何字符串值。我认为这里有些错误。 怎么得到这个?下面是我的代码,它根本不起作用 上面的代码返回对象未设置为实例错误! 问题答案: 假设您希望反序列化为具体的类(按照问题中第二种尝试的方法),那么您需要一个包装器类来容纳整个对象,然后对此进行反序列化。 目

  • 我正在尝试创建一个文件解析器,可以将多种类型的数据(用户、地址等)解析为结构。为此,我创建了一个名为Datatype的接口: 以及实现接口的几个结构: 前。 然后,我读取文件名,从文件名中获取它包含的数据类型,并创建该结构的实例以传递给解析器: 我这样做是希望我可以创建一个解析方法,该方法采用任何一个结构,检测类型并从csv记录中解封。然而,我发现我做不到这一点,因为我似乎无法从接口中获取底层类型

  • 问题内容: 我正在寻找如何使用golang从Kubernetes集群中的Pod获取日志的解决方案。我看过“ https://github.com/kubernetes/client- go ”和“ https://godoc.org/sigs.k8s.io/controller- runtime/pkg/client ”,但听不懂如何将它们用于此目的。除了日志外,我在获取K8S中的Pod或任何其他