JNA to Go DLL - 如何获取从 Go Func 返回的字符串?

JNA to Go DLL - How do I get String returned from Go Func?

我有一个 Java 程序正在使用 JNA 调用 Go Func。这是 Java 中 Go 函数的接口:

public interface GPG extends Library {
    // GoString class maps to: C type struct { const char *p; GoInt n; }
    public class GoString extends Structure {
        public static class ByValue extends GoString implements Structure.ByValue {}
        public String p;
        public long n;
        protected List getFieldOrder(){
            return Arrays.asList(new String[]{"p","n"});
        }
    }
    // Foreign functions
    public GoString.ByValue decrypt(GoString.ByValue encString, GoString.ByValue secretKeyring, GoString.ByValue passphrase);
}

Go 中的函数签名是:

func decrypt(encString string, secretKeyring string, passphrase string) string

Go 生成的 C header 有:

/* Created by "go tool cgo" - DO NOT EDIT. */

/* package command-line-arguments */


#line 1 "cgo-builtin-prolog"

#include <stddef.h> /* for ptrdiff_t below */

#ifndef GO_CGO_EXPORT_PROLOGUE_H
#define GO_CGO_EXPORT_PROLOGUE_H

typedef struct { const char *p; ptrdiff_t n; } _GoString_;

#endif

/* Start of preamble from import "C" comments.  */




/* End of preamble from import "C" comments.  */


/* Start of boilerplate cgo prologue.  */
#line 1 "cgo-gcc-export-header-prolog"

#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H

typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt64 GoInt;
typedef GoUint64 GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;

/*
  static assertion to make sure the file is being used on architecture
  at least with matching size of GoInt.
*/
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];

typedef _GoString_ GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

#endif

/* End of boilerplate cgo prologue.  */

#ifdef __cplusplus
extern "C" {
#endif


extern GoString decrypt(GoString p0, GoString p1, GoString p2);

#ifdef __cplusplus
}
#endif

我使用以下代码从 Java 调用 Go Func:

                GPG gpg = (GPG) Native.loadLibrary("C:/lib/gpg.dll", GPG.class);
                GPG.GoString.ByValue encString = new GPG.GoString.ByValue();
                encString.p = value;
                encString.n = encString.p.length();
                GPG.GoString.ByValue secretKeyring = new GPG.GoString.ByValue();
                secretKeyring.p = "c:/gnupg/secring.gpg";
                secretKeyring.n = secretKeyring.p.length();
                GPG.GoString.ByValue passphrase = new GPG.GoString.ByValue();
                passphrase.p = "SecretPassPhrase";
                passphrase.n = passphrase.p.length();
                GPG.GoString.ByValue decValue = gpg.decrypt(encString, secretKeyring, passphrase);

显然正在调用 func 并处理直到结果字符串的 return。但它随后产生:"panic: runtime error: cgo result has Go pointer" 如何从 Go 返回字符串结果? 使用go版本go1.10 windows/amd64, JNA 4.5.1, Java 1.8.0_152

您在 _GoString_ 中的 const char * 应该改用 Pointer,然后使用 Pointer.getString() 和提供的偏移量来获取实际的字符串。

如果 Go 本身拒绝 string return 值,您可能不得不填充调用者提供的缓冲区。

您的 GO 函数应如下所示:

//export decrypt
func decrypt(encString string, secretKeyring string, passphrase string) *C.char {
    //... your code here
    var str string = "returning string"
    return C.CString(str)
}

Java接口:

public String decrypt(GoString.ByValue encString, GoString.ByValue secretKeyring, GoString.ByValue passphrase);