通过JNA调用本机C ++函数的非确定性返回值(字符串类型) [英] Non-deterministic return values (string type) from calling native C++ functions through JNA

查看:582
本文介绍了通过JNA调用本机C ++函数的非确定性返回值(字符串类型)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题描述:

我的项目是JAVA,但我想调用C ++函数,该函数将一个字符串作为输入,并在处理后输出另一个字符串.我使用JNA来完成这项工作,并且String和char *是从JAVA到C ++的映射类型.(在处理过程中,我需要std :: string作为中间类型,详细给出了简单的代码.)

My project is JAVA but I want to call a C++ function, which takes a string as input and output another string after process. I apply JNA to do this work, and String and char* are mapping types from JAVA to C++.(During the processing, I need std::string as intermediate type, the simplyfied code is given out in detail.)

当输入字符串不长时,程序运行良好.但是,当我增加字符串的长度时(在这里,我将测试语句..."重复了6次),事情开始变得奇怪.我可以看到字符串在C ++程序中传递了(成功打印了出来),但是我在JAVA中收到了一个空字符串,这意味着它无法返回该字符串.而且,每次执行的while循环时间都不同(中断时打印出不同的计数).

The program runs well, when the input string is not long. However, when I increase the length of the string(here, I duplicate "test sentence..." for 6 times), things began strange. I can see the string is pass in C++ program(successfully print out), BUT I received an empty string in JAVA, which means it fails to return the string. What's more, the times of while loop is different on each excution(print out different count when break the loop).

然后

1.长度怎么了? JNA有任何限制吗?

2.我可以达到我的目标以及如何正确地在JNA中传递字符串吗?(顺便说一句,我尝试了Pointer的操作,但是不起作用)

谢谢,这是我的代码和一些环境细节

Thanks ahead, here is my code and some enviroment details

在C ++侧上进行编码>>>>>>>>>>> test.cpp

CODE ON C++ SIDE>>>>>>>>>>>test.cpp

#include<iostream>
using namespace std;
extern "C" __attribute__((visibility("default"))) const char* SeudoCall(const char* input); 
const char* SeudoCall(const char* str){
    std::string input(str);
    std::cout<<"in C:"<<input<<std::endl;
    return input.c_str();
}

COMPILE C ++库>>>>>>>>>

COMPILE C++ LIBRARY>>>>>>>>>

g++ test.cpp -fpic -shared -o libtest.so

在Java端进行编码>>>>>>>>>>>

CODE ON JAVA SIDE>>>>>>>>>>>

import com.sun.jna.Library;
import com.sun.jna.Native;
public class TestSo {
    public interface LgetLib extends Library {
        LgetLib INSTANCE = (LgetLib) Native.loadLibrary("test", LgetLib.class);
        String SeudoCall(String input);
    }
    public String SeudoCall(String input){
        return LgetLib.INSTANCE.SeudoCall(input);
    }
    public static void main(String[] args) {
        TestSo ts = new TestSo();
        String str = "test sentence...test sentence...test sentence...test sentence...test sentence...test sentence...";
        String retString;
        int count=0;
        while(true){
            System.out.println("count:"+(++count));
            retString=ts.SeudoCall(str);
            System.out.println("in JAVA:"+retString);
            if(retString.equals("")){
                System.out.println("break");
                break;
            }
        }
    }
}

运行详细信息>>>>>>>>>>>>

RUN DETAIL>>>>>>>>>>>

Intel Core i7-4790 3.60GHz
gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
JNA 4.1.0
java version "1.8.0_31"
Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)

推荐答案

您的C ++代码马上就出现了问题.您正在返回一个指向本地std::string的指针,该指针将在该函数存在时被销毁.因此,您正在引入未定义的行为.

You have a problem with your C++ code right away. You are returning a pointer to a local std::string that will be destroyed when the function exists. Thus you are introducing undefined behavior.

换句话说,即使应用程序全部是C ++,您的函数也会出现错误,因此它不仅是Java/JNA/C ++问题,而且本身就是C ++问题.

In other words, your function would be buggy even if the application were all C++, so it isn't solely a Java/JNA/C++ issue, but a C++ issue in itself.

const char* SeudoCall(const char* str){
    std::string input(str);
    std::cout<<"in C:"<<input<<std::endl;
    return input.c_str();  // <-- this is no good.
}

c_str()绑定到局部变量input.当函数退出时,发生input的析构函数,并伴随着表示字符串的c_str().

The c_str() is tied to the local variable input. When the function exits, the destructor for input takes place, taking along with it the c_str() that represented the string.

要解决此问题,您必须将字符串返回到Java,该字符串将在函数返回后变为有效".我不知道JNA,但是对于JNI,您可以使用JNI NewStringUTF函数创建将作为jstring返回的字符串.

To fix this, you have to return a string back to Java that will be "alive" after the function returns. I do not know JNA, but for JNI, you use the JNI NewStringUTF function to create a string that will be returned as a jstring.

也许此链接会为您提供帮助:

Maybe this link will help you:

如何退货char * aarr =使用JNA从C ++到Java的新char [200]

当输入字符串不长时,程序运行良好.然而, 当我增加字符串的长度时(在这里,我复制"test 句子..." 6次),事情开始变得奇怪.我可以看到字符串 在C ++程序中通过(成功打印出),但是我收到了 JAVA中的空字符串,这意味着它无法返回该字符串. 而且,每个循环的while循环时间都不相同 执行(在中断循环时打印出不同的计数).

The program runs well, when the input string is not long. However, when I increase the length of the string(here, I duplicate "test sentence..." for 6 times), things began strange. I can see the string is pass in C++ program(successfully print out), BUT I received an empty string in JAVA, which means it fails to return the string. What's more, the times of while loop is different on each excution(print out different count when break the loop).

您目睹的是未定义的行为.从C ++函数返回的指针可能是,它指向保存字符的内存,但是正如您的测试所显示的那样,不应依赖于该指针.

What you are witnessing is undefined behavior. The pointer returned from your C++ function may be pointing to the memory that holds the characters, but it is not to be relied on, as your testing is showing you.

这篇关于通过JNA调用本机C ++函数的非确定性返回值(字符串类型)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆