简体   繁体   English

使用 cgo 从 Go 返回 String[]

[英]Return String[] from Go using cgo

I have to call a Go function from Java.我必须从 Java 调用 Go 函数。 I am using cgo and JNA for doing this.我正在使用cgoJNA来做这件事。

The only thing that the Go routine does is allocating memory and return a char** . Go 例程所做的唯一一件事就是分配内存并返回一个char** From Java side, I am receiving the char** using String[] as is mentioned in the documentation .从 Java 方面,我正在使用文档中提到的String[]接收char**

Below are the details of the C helper and Go functions:下面是 C helper 和 Go 函数的详细信息:

static char** cmalloc(int size) {
    return (char**) malloc(size * sizeof(char*));
}

static void setElement(char **a, char *s, int index) {
    a[index] = s;
}

//export getSearchKeysA
func getSearchKeysA() **C.char {
    set_char := C.cmalloc(1)
    defer C.free(unsafe.Pointer(set_char))
    C.setElement(set_char, C.CString("hello world"), C.int(0))
    return set_char
}

The Java side: Java方面:

String[] getSearchKeysA();

The error I am getting is:我得到的错误是:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007fff6b15323e, pid=92979, tid=0x0000000000000c07
#
# JRE version: Java(TM) SE Runtime Environment (8.0_192-b12) (build 1.8.0_192-b12)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.192-b12 mixed mode bsd-amd64 compressed oops)
# Problematic frame:
# C  [libsystem_kernel.dylib+0x723e]  __pthread_kill+0xa
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /Users/dfb3/datafabric/pocs/go-java-connector/hs_err_pid92979.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

What I have noticed is that the issue appears when malloc is allocating memory.我注意到问题是在 malloc 分配内存时出现。

I already tried doing ulimit -c unlimited and removing the defer C.free(unsafe.Pointer(set_char)) from the method.我已经尝试执行ulimit -c unlimited并从方法中删除defer C.free(unsafe.Pointer(set_char))

What can be the cause of the error and how can I solve it?错误的原因是什么,我该如何解决? Is there any other way of returning a []string from Go using JNA ?有没有其他方法可以使用JNA从 Go 返回[]string

Update because of typo and base on @PeterSO answer :由于打字错误和基于@PeterSO 回答而更新:

  1. I wrote initially malloc(0) but it should be malloc(1)我最初写的是 malloc(0) 但它应该是 malloc(1)
  2. func C.CString(string) *C.char , it should allocate the memory for me, is not? func C.CString(string) *C.char ,它应该为我分配内存,不是吗?

I could finally return a String[] from GO using cgo .我终于可以使用cgoGO返回一个String[]

I will leave the functions signatures:我将留下函数签名:

//export getSearchKeys
func getSearchKeys(numKeysByReference *C.int) **C.char {
  *numKeysByReference = // ... some value
  // Using the C helper defined above
  set_char := C.cmalloc(*numKeysByReference)
  // Logic allocating and populating C.char[i .. *numKeysByReference]
  // ...
  return set_char
}

After creating the **C.char structure using cgo , on Java side, I am receiving the data as follow:使用cgo创建**C.char结构后,在Java端,我收到的数据如下:

IntByReference intByReference = new IntByReference();
PointerByReference array = lib.getSearchKeys(intByReference);
String[] results = array.getPointer().getStringArray(0, intByReference.getValue());

As @PeterSO mentioned, we have call defer C.free() after using it.正如@PeterSO 提到的,我们在使用之后调用了defer C.free() Otherwise, it will be deallocated after returning.否则,它将在返回后被释放。

You write:你写:

func getSearchKeysA() **C.char {
    set_char := C.cmalloc(0)
    defer C.free(unsafe.Pointer(set_char))
    C.setElement(set_char, C.CString("hello world"), C.int(0))
    return set_char
}

Which likely executes as:这可能执行为:

func getSearchKeysA() (retval **C.char) {
    set_char := C.cmalloc(42)
    C.setElement(set_char, C.CString("hello world"), C.int(1))
    retval = set_char
    C.free(unsafe.Pointer(set_char))
    return retval
}

Are you referring to set_char after free ?你指的是set_char after free吗?


The Go Programming Language Specification Version of July 31, 2019 2019 年 7 月 31 日Go 编程语言规范版本

Defer statements推迟声明

A "defer" statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement, reached the end of its function body, or because the corresponding goroutine is panicking. “defer”语句调用一个函数,该函数的执行被推迟到周围函数返回的那一刻,因为周围函数执行了一个 return 语句,到达了它的函数体的末尾,或者因为相应的 goroutine 处于恐慌状态。


You write:你写:

set_char := C.cmalloc(0)

static char** cmalloc(int size) {
    return (char**) malloc(size * sizeof(char*));
}

$ man malloc $ man malloc

The malloc() function allocates size bytes and returns a pointer to the allocated memory. malloc() 函数分配 size 字节并返回指向已分配内存的指针。 The memory is not initialized.内存未初始化。 If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().如果 size 为 0,则 malloc() 返回 NULL 或稍后可以成功传递给 free() 的唯一指针值。

Why allocate size 0 (zero)?为什么分配大小 0(零)?

malloc memory is not initialized. malloc内存未初始化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM