Convert C.jstring to native string in Go

huangapple go评论86阅读模式
英文:

Convert C.jstring to native string in Go

问题

如何将C.jstring转换为可用的Go字符串?

您可以使用以下方法将C.jstring转换为可用的Go字符串:

func Java_ClassName_MethodName(env *C.JNIEnv, clazz C.jclass, javaString C.jstring) {
    defer func() {
        if err := recover(); err != nil {
            log.Fatalf("panic: init: %v\n", err)
        }
    }()

    nativeString := C.GoString((*C.char)(C.GetStringUTFChars(env, javaString, nil)))

    // 使用您的字符串

    C.ReleaseStringUTFChars(env, javaString, (*C.char)(unsafe.Pointer(nativeString)))
}

这里使用了C.GoString函数将C字符串转换为Go字符串。在调用GetStringUTFChars函数时,需要将返回的指针转换为(*C.char)类型,然后使用C.GoString将其转换为Go字符串。最后,使用ReleaseStringUTFChars函数释放内存。

请注意,这只是一个示例代码片段,您需要根据您的实际需求进行适当的修改和错误处理。

英文:

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)
	   }
   }()
   // ???
}

答案1

得分: 1

我知道这个问题很旧,但最近我遇到了这个问题,并且想为其他人提供一些详细说明:

GetStringUTFChars这样的JNI函数是无法直接从Go中调用的函数指针。你需要在一个单独的C文件中包装这些函数,例如:

jx.c

#include <jni.h>

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

在从C文件创建库之后,你的Go文件将如下所示:

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() {}

之所以有一个单独的C文件只用于包装函数,是因为在文档中有这样一个条款:

在文件中使用//export会对前言产生限制:由于它被复制到两个不同的C输出文件中,因此它不能包含任何定义,只能包含声明。

英文:

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
> c
&gt; #include &lt;jni.h&gt;
&gt;
&gt; const char* jx_GetStringUTFChars(JNIEnv *env, jstring str, jboolean *isCopy) {
&gt; return (*env)-&gt;GetStringUTFChars(env, str, isCopy);
&gt; }
&gt;

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 &quot;jx.h&quot;
*/
import &quot;C&quot;
import (
    &quot;fmt&quot;
)

//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.

答案2

得分: 0

如果我是你,我会寻找Java到C字符串的方法,然后使用标准的C字符串转换为Go字符串。

我会考虑编写一个C函数,将Java字符串转换为C字符串,并将其返回给Go运行时。

C到Go字符串的转换:

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

Java有自己的内存管理方式,因此应该有自己的方法将数据传递到C中。你可以使用Java JNI关键字来实现。

你正在一个进程中同时使用Java和Go运行时,这可能会产生一些副作用。

英文:

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.

huangapple
  • 本文由 发表于 2014年7月28日 21:05:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/24995953.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定