20

How can I convert a C.jstring to a usable string in Go?

I am using GoAndroid.

In C you can do something like in this stackoverflow thread

JNIEXPORT void JNICALL Java_ClassName_MethodName(JNIEnv *env, jobject obj, jstring javaString)   
{
   const char *nativeString = (*env)->GetStringUTFChars(env, javaString, 0);

  // use your string

  (*env)->ReleaseStringUTFChars(env, javaString, nativeString);
}

in Go it starts to look something like this

func Java_ClassName_MethodName(env *C.JNIEnv, clazz C.jclass, jstring javaString) {
    defer func() {
        if err := recover(); err != nil {
           log.Fatalf("panic: init: %v\n", err)
       }
   }()
   // ???
}
Community
  • 1
  • 1
jarradhope
  • 303
  • 2
  • 5
  • 4
    You can convert a java string to a c string (before call go func) then convert a c string to a go string by C.GoString() – chendesheng Jul 28 '14 at 13:17

2 Answers2

1

I know this question is old, but I recently ran into this and thought I'd elaborate a bit for anyone else that winds up here:

JNI functions like GetStringUTFChars are function pointers that cannot be called directly from Go. You have to wrap the functions in a separate C file, e.g.:

jx.c
#include <jni.h>

const char* jx_GetStringUTFChars(JNIEnv *env, jstring str, jboolean *isCopy) {
    return (*env)->GetStringUTFChars(env, str, isCopy);
}

After creating a library from the C file, your Go file will look something like this:

package main

/*
#cgo CFLAGS: -I/usr/java/jdkX.X.X_XXX/include/ -I/usr/java/jdkX.X.X_XXX/include/linux/
#cgo LDFLAGS: -L${SRCDIR}/ -ljx

#include "jx.h"
*/
import "C"
import (
    "fmt"
)

//export Java_com_mypackage_MyClass_print
func Java_ClassName_MethodName(env *C.JNIEnv, clazz C.jclass, str C.jstring) {
    s := C.jx_GetStringUTFChars(env, str, (*C.jboolean)(nil))
    fmt.Println(C.GoString(s))
}

func main() {}

The reason why there is a separate C file just for the wrapper function is because of this clause in the documentation:

Using //export in a file places a restriction on the preamble: since it is copied into two different C output files, it must not contain any definitions, only declarations.

syntaqx
  • 2,636
  • 23
  • 29
0

If I were you, I'd look for Java to C string and then use standard C string to Go string.

I would consider writing a C function that converts Java string into C string and returns that back to Go runtime.

C to GoString:

b := C.malloc(50)
defer C.free(unsafe.Pointer(b))
C.callToCFunction(PChar(b), 50)
rs := C.GoString(PChar(b))
return rs, err

Java has its own memory management and thus should have its own way of moving data into C. You may ask with Java JNI keywords.

You are using Java and Go runtimes in one process. This may have some side-effects.

Stefan Steiger
  • 78,642
  • 66
  • 377
  • 442
Sergei G
  • 1,561
  • 3
  • 18
  • 26