代码之家  ›  专栏  ›  技术社区  ›  ChronicUser

将JNI(C++)代码中的字符串返回到Java

  •  1
  • ChronicUser  · 技术社区  · 7 年前

    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++中的本机函数读取ram的内容,然后将其作为字符串或字符数组返回给java进行进一步处理。

    问题:

    的返回值 jstring result

        #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;
    }
    

    1、不是权限问题 2.Ram地址正确,我知道那里存储了什么。我怎么知道? 3.阅读更多关于UTF_8和UTF_16的信息(问题很可能在这里)

    操作系统:Linux 64位Fedora

    问题:

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

    然后感谢你们的时间和努力。

    2 回复  |  直到 7 年前
        1
  •  0
  •   geza    7 年前

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

    如果要继续使用字符串,则必须将字节转换为这种修改的utf-8编码(因此必须将大于127和0的字节值转换为2个字节)。

    但正如Jorn在评论中所建议的那样,您需要使用 ByteBuffer 或者一个简单的字节数组( byte[] )相反,因为它更为优化:使用 String

        2
  •  -1
  •   ChronicUser    7 年前

    我设法让它工作,但需要一些修补。下面的代码可以与我发布的原始代码结合使用 对所有人来说,我会尽力投票决定答案。

    public static void main(String[] args){
            MainClass app = new MainClass();
    
                byte[] x = app.readRam(4096, 0x556cbdb2a000L, 22444);
    
                System.out.println(x.length);
                System.out.write(x, 0, x.length);
    
                for(int i=0; i<x.length; i++)
                {   
                    if((int)x[i] >= 32 && (int)x[i] < 127)
                    {
                        System.out.print((char)x[i]);
                    }
                }
    
                char c = 120;
                System.out.println("\n" + c);
    
        }