gpt4 book ai didi

java - 将字符串从 JNI (C++) 代码返回到 Java

转载 作者:太空宇宙 更新时间:2023-11-04 14:29:41 27 4
gpt4 key购买 nike

Java 代码:

public class MainClass 
{
static
{
System.load("/home/chronic/workspace/ramRead/src/libRamRead.so");
}
private native String readRam(int len, long addr, int pid);
private native int readSize();

public static void main(String[] args)
{
MainClass app = new MainClass();


String x = app.readRam(4096, 0x55c5520b5000L, 4435);

//System.out.println("HEY THERE");
// System.out.println("I BEGIN HERE");
System.out.println(x.length());

//int test = app.readSize();
//System.out.println(test);
}
}

这是我的原生函数 (C++)

JNIEXPORT jstring JNICALL Java_ramRead_MainClass_readRam
(JNIEnv *env, jobject, jint len, jlong addr, jint pid)
{
struct iovec local[1];
struct iovec remote[1];
char buf[len];
jstring result;
//jcharArray buf = (*env).NewCharArray(len);
//jcharArray buf1 = (*env).NewCharArray(len);

local[0].iov_base = buf;
local[0].iov_len = len;

remote[0].iov_base = (void *) addr;
remote[0].iov_len = len;

nread = process_vm_readv(pid, local, 1, remote, 1, 0);

//printf("len %d, pid %d, addr %li, buf %c, size of buf %d ", len, pid, addr, buf, sizeof(buf));
printf("\nTHIS MUCH: %d\n", nread);

for(int i=0; i<4096; i++){
printf("%c", buf[i]);
}

//(*env).SetCharArrayRegion(buf1, 0, len, buf);
result = (*env).NewStringUTF(buf);
//printf("RESULT: %s", (*env).GetStringUTFLength(result));

return result;
}

我的目标:

让C++中的native函数读取ram中的内容,然后以字符串或char数组的形式返回给java做进一步处理。

问题:

jstring 结果 的返回值不是我预期的 java 中的值,存在几个问题,首先它的长度为 7 而不是预期的 4096。另一个问题是输出是荒谬的。我有另一个用 C++ 编写的程序,它基本上读取 RAM 的内容,然后将它们打印到控制台。这是下面的代码,它就像一个魅力。我知道从哪个地址读取,我知道期望的结果,只要我使用 C++,它就可以正常工作,但只要我使用相同的 JNI出现上述问题前的方法。

    #include <jni.h>
#include "ramRead_MainClass.h"
#include <sys/uio.h>

static ssize_t nread;

JNIEXPORT jbyteArray JNICALL Java_ramRead_MainClass_readRam
(JNIEnv *env, jobject, jint len, jlong addr, jint pid)
//JNIEXPORT jbyteArray JNICALL Java_ramRead_MainClass_readRam
//(JNIEnv *env, jobject, jobject len, jobject addr, jint pid)
{
struct iovec local[1];
struct iovec remote[1];
jbyte buf[len];
jbyteArray buf1 = (*env).NewByteArray(len);

local[0].iov_base = buf;
local[0].iov_len = len;

remote[0].iov_base = (void *) addr;
remote[0].iov_len = len;

nread = process_vm_readv(pid, local, 1, remote, 1, 0);

(*env).SetByteArrayRegion(buf1, 0, len, buf);
return buf1;
}

JNIEXPORT jint JNICALL Java_ramRead_MainClass_readSize
(JNIEnv *, jobject)
{
return nread;
}

到目前为止我已经尝试过:

检查 list 1.不是权限问题2. ram地址是正确的,我知道那里存储了什么。我怎么知道? 我正在读取计算器的 RAM,我正在寻找我输入的一组特定数字。使用 C++,我找到了它们,但使用 jni 却找不到。3. 阅读更多有关 UTF_8 和 UTF_16 的信息(问题很可能出在这里)4.看到这里的帖子试图重现解决方案,但无济于事。

操作系统:Linux 64 位 Fedora

问题:

如何将 C++ 字符串转换为 jstring,然后在 java 中将其返回并打印出来,以便输出与上面列出的 C++ 程序的输出匹配。

无论如何,这就是我打算解决它的方式,但如果有人有更好的解决方案或功能性解决方案,我会更乐意接受。

那么请大家付出时间和精力。

最佳答案

JNI 将字符串存储在 modified utf-8 encoding 中(见页面底部)。

如果你想继续使用字符串,那么你必须将你的字节转换成这种修改后的 utf-8 编码(所以字节值 >127 和零必须转换成 2 个字节)。

但正如 Jorn 在评论中建议的那样,您需要使用 ByteBuffer 或简单的字节数组 (byte[]),因为它更优化:使用 String 会浪费内存,因为它包含 16 位元素。

关于java - 将字符串从 JNI (C++) 代码返回到 Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44782644/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com