gpt4 book ai didi

python - 从 Go 内置的共享库中返回 Python 中的数组

转载 作者:行者123 更新时间:2023-12-01 22:22:59 27 4
gpt4 key购买 nike

我有以下 Go 文件:

package main

import "C"

//export stringList
func stringList(a, b string) []string {
var parserString[] string
parserString = append(parserString, a)
parserString = append(parserString, b)
return parserString
}

func main() {}

然后我使用 go build -o stringlist.so -buildmode=c-shared stringlist.go 构建

然后,我尝试在 Python 中使用
from ctypes import *
lib = cdll.LoadLibrary("./stringlist.so")
lib.stringList.argtypes = [c_wchar_p, c_wchar_p]
lib.stringList("hello", "world")

但收到错误
panic: runtime error: cgo result has Go pointer

goroutine 17 [running, locked to thread]:
main._cgoexpwrap_0de9d34d4a40_stringList.func1(0xc00005ce90)
_cgo_gotypes.go:46 +0x5c
main._cgoexpwrap_0de9d34d4a40_stringList(0x7f9fdfa8eec0, 0x7f9fddaffab0, 0x7f9fdd8f46cf, 0x7ffc501ce460, 0xc00000e040, 0x2, 0x2)
_cgo_gotypes.go:48 +0x11b
Aborted (core dumped)

问题是什么?我该如何解决?是 stringList没有返回正确的类型?

最佳答案

如评论中所述,您需要转换为 C返回任何值之前的类型,这意味着您的函数应该返回 **C.char . Go 文档具有从 *C.chart 转换的函数至C.GoString .

  • Cgo Wiki
  • CGO Documentation

  • 这是一个简单但可能有泄漏的函数;在 Cgo 你负责
    内存管理,这个特定的函数分配结果内存,但如果你在调用 Cgo 之前知道函数你需要多少内存或空间可以预先分配它。

    它所做的只是将提供的字符串转换为大写。

    package main

    /*
    #include <stdlib.h>
    */
    import "C"

    import (
    "fmt"
    "strings"
    "unsafe"
    )

    //export stringList
    func stringList(a, b *C.char) **C.char {
    // convert to Go strings
    goStringA := C.GoString(a)
    goStringB := C.GoString(b)

    //... do something with the strings ...
    fmt.Println("CGO: ", goStringA)
    fmt.Println("CGO: ", goStringB)

    goStringA = strings.ToUpper(goStringA)
    goStringB = strings.ToUpper(goStringB)

    // Convert back to C strings
    // This strings _WILL NOT_ be garbage collect
    // it may be that we want to free them.
    // https://github.com/golang/go/wiki/cgo#go-strings-and-c-strings
    ra := C.CString(goStringA)
    rb := C.CString(goStringB)

    // Allocate memory for our result pointer
    resultMem := C.malloc(C.size_t(2) * C.size_t(unsafe.Sizeof(uintptr(0))))

    // Assign to the results var
    // https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices
    result := (*[1<<30 - 1]*C.char)(resultMem)
    (*result)[0] = ra
    (*result)[1] = rb

    return (**C.char)(resultMem)
    }

    func main() {}

    因为我在 macOS计算机我必须像这样构建它:
    go build -o stringlist.dylib -buildmode=c-shared main.go

    然后我可以使用以下 Python 代码运行它:

    #!/usr/bin/env python3
    from ctypes import *

    lib = cdll.LoadLibrary('./stringlist.dylib')

    lib.stringList.argtypes = [c_char_p, c_char_p]
    lib.stringList.restype = POINTER(c_char_p)

    result = lib.stringList("hello".encode(), "world".encode())
    for word in result:
    if word:
    print(word.decode('utf-8'))

    NOTE: The python code produces a segfault; I'm guessing that it's because I'm not using correctly the ctypes module as I'm not that familiar with. However the following C code does not segfault.



    #include <stdlib.h>
    #include "stringlist.h"
    #include <dlfcn.h>

    int main(int n, char **args) {
    char lib_path[1000];
    sprintf(lib_path, "%s/stringlist.dylib", args[1]);
    void *handle = dlopen(lib_path, RTLD_LAZY);

    char** (*stringList)(char*, char*) = dlsym(handle, "stringList");
    const char *a = "hello";
    const char *b = "world";
    char **result = stringList(a, b);
    for (size_t i = 0; i< 2; i++) {
    printf("%s\n", result[i]);
    }

    return 0;
    }

    像这样构建它:
    clang main.c -o crun && ./crun

    关于python - 从 Go 内置的共享库中返回 Python 中的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61898877/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com