JNA to Go DLL - 如何从Go Func返回String?

时间:2018-03-29 02:56:08

标签: jna cgo

我有一个使用JNA调用Go Func的Java程序。这是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签名是:

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

Go生成的C标头有:

/* 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并处理结果字符串的返回。但它产生:“恐慌:运行时错误:cgo结果有Go指针” 如何从Go获取String结果? 使用go版本go1.10 windows / amd64,JNA 4.5.1,Java 1.8.0_152

2 个答案:

答案 0 :(得分:1)

您的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);

答案 1 :(得分:0)

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

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