标签: cgo

如何使用伪 CGO 指令在子目录中添加 C 文件作为 go build 的一部分?

根据文档,go build使用 cgo 将在包的根目录中添加任何 C/C++ 文件作为编译的一部分。有没有办法通过使用 CGO 指令使给定子目录中的 C/C++ 文件也成为编译的一部分以及根目录中的文件?

go cgo

5
推荐指数
1
解决办法
958
查看次数

如何在 Go 中填写 void* C 指针?

我正在尝试与 Go 中的一些 C 代码交互。使用 cgo,这一直相对简单,直到我遇到这种(相当常见的)情况:需要将指针传递给本身包含指向某些数据的指针的结构。如果不诉诸于将结构的创建放入 C 代码本身,我似乎无法弄清楚如何从 Go 中做到这一点,我不想这样做。这是一个说明问题的片段:

package main

// typedef struct {
//     int   size;
//     void *data;
// } info;
//
// void test(info *infoPtr) {
//     // Do something here...
// }
import "C"

import "unsafe"

func main() {
    var data uint8 = 5
    info := &C.info{size: C.int(unsafe.Sizeof(data)), data: unsafe.Pointer(&data)}
    C.test(info)
}
Run Code Online (Sandbox Code Playgroud)

虽然编译正常,但尝试运行它会导致:

panic: runtime error: cgo argument has Go pointer to Go pointer
Run Code Online (Sandbox Code Playgroud)

在我的例子中,传递给 C 调用的数据在调用后不会持续存在(即,有问题的 C 代码深入结构,复制它需要的内容,然后返回)。

go cgo

5
推荐指数
1
解决办法
3580
查看次数

如何在go中将指向切片的指针传递给C函数

背景:使用 cgo 从 Golang 调用 C 函数。

我想用它有这个签名C函数:int f(int *count, char ***strs)。它将修改countand的数据strs,这就是它使用指向它们的指针的原因。的值count是 的长度strsstrs是一个字符串数组;返回值只是一个(布尔值)指示符,用于说明是否存在错误。

在golang中,我可以count通过使用成功通过和修改C.f((*C.int)(&count));通过[]string使用[]*C.char. 示例代码是这样的:

/*
#include <stdio.h>
int f(int *c, char **str) {
    int i;
    printf("%d\n", *c);
    for (i = 0; i < *c; i++) {
        printf("%s\n", str[i]);
    }
    *c = (*c) + 1;
    return 1;
}
*/
import "C"
func go_f(strs []string) int {
    count := len(strs)
    c_count …
Run Code Online (Sandbox Code Playgroud)

c go cgo

5
推荐指数
1
解决办法
3740
查看次数

如何获得 cgo (golang) 的语法高亮

cgo 在 go 中写在“comments”中,这意味着默认情况下它被赋予注释语法突出显示。有适当的 golangC 语法突出显示会很好但在 cgo 文件中。

package main

// ... C code or #include here ...
import "C"

... Go code here ...
Run Code Online (Sandbox Code Playgroud)

例子

无论是 Visual Studio Code 还是 ViM,我都喜欢这个。

如何做到这一点?

syntax-highlighting go cgo visual-studio-code

5
推荐指数
1
解决办法
914
查看次数

使用 CGo 调用带有双指针输出参数的 C 函数

我试图找出调用此函数的正确方法:

size_t
fz_buffer_storage(fz_context *ctx, fz_buffer *buf, unsigned char **datap)
{
    if (datap)
        *datap = (buf ? buf->data : NULL);
    return (buf ? buf->len : 0);
}
Run Code Online (Sandbox Code Playgroud)

使用 CGo 获取底层字符串及其长度作为 Go 中的字节数组。

这是正确的方法吗?

var bufferContents *C.uchar
length := C.fz_buffer_storage(ctx, buf, &bufferContents)
bytes := C.GoBytes(unsafe.Pointer(bufferContents), C.int(length))
Run Code Online (Sandbox Code Playgroud)

由于 C 代码覆盖了*datap,我不确定垃圾收集器是否仍然会做正确的事情。

我在这里看到一个答案暗示了一些类似的东西

var tempUcharPtr *C.uchar
bufferContents := C.malloc(C.size_t(unsafe.Sizeof(tempUcharPtr)))
defer C.free(bufferContents)
length := C.fz_buffer_storage(ctx, buf, (**C.uchar)(bufferContents))
bytes := C.GoBytes(unsafe.Pointer(*(**C.uchar)(bufferContents)), C.int(length))
Run Code Online (Sandbox Code Playgroud)

这似乎也有效,但它更复杂,我想知道它是否比以前的版本更好/更安全。

c garbage-collection pointers go cgo

5
推荐指数
1
解决办法
1448
查看次数

如何将 C.double 数组传递给 Cgo 函数?

我刚刚开始使用 CGo,我正在尝试将数据发送到 C 库,该库对浮点数/双精度数数组执行统计计算。我现在想弄清楚的是如何将浮点数组或 C.double 的数组发送到具有如下签名的 CGo 函数:

double pop_mean(int numPoints, double a[])
Run Code Online (Sandbox Code Playgroud)

我已经想出了如何在那里输入 C.int,但是我在弄清楚如何发送双打数组时遇到了麻烦。

我还没有看到任何关于这件事的博客文章或 SO 问题,所以我想我会问。

以下是我迄今为止最大的努力。

// Get a basic function to work, while passing in an ARRAY  arr := make([]C.double, 0)
arr = append(arr, C.double(10.0))
arr = append(arr, C.double(20.0))
arr = append(arr, C.double(30.0))
var fixedArray [3]C.double = arr[:]

// ptr := C.CBytes(arr)
// defer C.free(unsafe.Pointer(ptr))

coolMean := C.pop_mean(3, &fixedArray)
fmt.Println("pop_mean (10, 20, 30): ", coolMean)
Run Code Online (Sandbox Code Playgroud)

这是我得到的错误:

./main.go:64:6: cannot use arr[:] (type []_Ctype_double) as type [3]_Ctype_double in …
Run Code Online (Sandbox Code Playgroud)

go cgo

5
推荐指数
1
解决办法
4460
查看次数

如何在cgo中访问全局变量?

结构的内存已经分配。

我想在 golang 中接近 C 结构。

我想在没有c代码的情况下访问golang中的struct变量,我该怎么办?

package main

/*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct 
{
        int   num;
        char  food[10];
        char  animal[128];
} sample;

sample *sa;

static void alloc() {
        sa = (sample *) malloc (sizeof(sample) * 2);
        memset(sa, 0, sizeof(sample) * 2);

        sa[0].num = 10;
        strcpy(sa[0].food, "noodle");
        strcpy(sa[0].animal, "cat");

    sa[1].num = 20;
    strcpy(sa[1].food, "pizza");
    strcpy(sa[1].animal, "dog");
}

*/
import "C"

import "fmt"

func init() {
        C.alloc()
}
func main() {
        fmt.Println(C.sa[0].num)
        fmt.Println(C.sa[0].food)
        fmt.Println(C.sa[0].animal)

        fmt.Println(C.sa[1].num)
        fmt.Println(C.sa[1].food)
        fmt.Println(C.sa[1].animal) …
Run Code Online (Sandbox Code Playgroud)

go cgo

5
推荐指数
1
解决办法
576
查看次数

如何在 Go 中访问 C 位域

我有一个像这样的结构:

typedef struct st_MASK_SETTINGS
{
  uint32_t foo  : 1;
  uint32_t bar  : 7;
} MASK_SETTINGS
Run Code Online (Sandbox Code Playgroud)

现在我想通过 cgo 访问foo- 但找不到任何文档如何做到这一点。

天真的v := ms.foo抱怨has no field or method

go cgo

5
推荐指数
1
解决办法
918
查看次数

使用 cgo 依赖项构建时间很慢

我有一个使用 Qt 包装器库https://github.com/therecipe/qt的 Go 程序。不幸的是,它的构建时间变得非常长(假设它是 go 部分)

go build -i .  // takes about 14 seconds
go run .       // takes about 8 seconds
Run Code Online (Sandbox Code Playgroud)

运行上述任一命令后,我在$GOPATH/pkg/linux_amd64/github.com/therecipe/qtas.a文件中获得了预编译的依赖项,因此它们不会每次都重新构建。

我尝试使用https://github.com/therecipe/qt/wiki/Faster-builds-(Linux) 中描述的ccacheGold 链接器/usr/bin/ld.gold,但它没有任何改进。这个 Qt 包装器也附带了我尝试过的自己的构建工具,但它的构建时间大致相同。qtdeploy

我正在运行的系统:

go version go1.14.4 linux/amd64
Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz
16GB Ram
Run Code Online (Sandbox Code Playgroud)

有谁知道是否有可能至少改善一点构建时间?

编辑:

运行go build -x .显示最大的时间消费者是以下命令

~/.go/pkg/tool/linux_amd64/link -o $WORK/b001/exe/a.out -importcfg $WORK/b001/importcfg.link -buildmode=exe -buildid=k8lYa6JYqRdCY9Gyt0jX/16myMybByG5X6rOfaRpS/WHdW2kCTfMCZs2I4x9WE/k8lYa6JYqRdCY9Gyt0jX -extld=g++ ~/.cache/go-build/b5/b5e47b7f77c2df06ba69937dc8b1399b1289b7c90d2e08b3341fdf13e119c860-d
Run Code Online (Sandbox Code Playgroud)

qt go build-time cgo

5
推荐指数
0
解决办法
451
查看次数

CGO 指针检查中的已知实现错误

根据 CGO 的文档(https://pkg.go.dev/cmd/cgo),在实现中有一个已知的错误:

注意:当前的实现有一个错误。虽然 Go 代码允许将 nil 或 C 指针(但不是 Go 指针)写入 C 内存,但如果 C 内存的内容看起来是 Go 指针,当前实现有时可能会导致运行时错误。因此,如果 Go 代码要在其中存储指针值,请避免将未初始化的 C 内存传递给 Go 代码。在将 C 中的内存传递给 Go 之前将其清零。

我在 GitHub 的问题跟踪器中寻找过这个,但在那里找不到。有人可以详细说明为什么会发生这种情况吗?运行时如何在未初始化的 C 内存中找到 Go 指针?

例如。假设我将一个未初始化的字符数组传递给 C 中的 Go 函数,运行时如何解释该内存中的 Go 指针?

此外,“如果 Go 代码将在其中存储指针值”部分让我感到困惑。为什么以后使用这个内存很重要?

go cgo

5
推荐指数
1
解决办法
99
查看次数