问题描述:
我的项目是JAVA,但我想调用一个C ++函数,它接受一个字符串作为输入并在处理后输出另一个字符串。我应用JNA来完成这项工作,而String和char *是从JAVA到C ++的映射类型。(在处理过程中,我需要std :: string作为中间类型,详细给出了简单的代码。)
当输入字符串不长时,程序运行良好。但是,当我增加字符串的长度时(这里,我复制了“测试句......”6次),事情开始变得奇怪了。我可以看到字符串是在C ++程序中传递的(成功打印出来),但是我在JAVA中收到一个空字符串,这意味着它无法返回字符串。更重要的是,while循环的次数在每次执行时都是不同的(打破循环时打印出不同的计数)。
然后,
1。长度有什么问题? JNA有任何限制吗?
2。我可以达到我的目标以及如何正确地在JNA中传递字符串吗?(顺便说一下,我尝试过Pointer的东西,但它不起作用)
先来感谢,这是我的代码和一些环境细节
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 ++ LIBRARY&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;
g++ test.cpp -fpic -shared -o libtest.so
JAVA SIDE上的代码&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;
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&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;
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)
答案 0 :(得分:1)
您的C ++代码有问题。您将返回一个指向本地std::string
的指针,该函数将在函数存在时被销毁。因此,您将引入未定义的行为。
换句话说,即使应用程序都是C ++,你的函数也会出错,所以它不仅仅是一个Java / JNA / C ++问题,而是一个C ++问题。
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()
。
要解决这个问题,你必须将一个字符串返回给Java,这将是&#34; alive&#34;函数返回后。我不知道JNA,但对于JNI,您使用JNI NewStringUTF
函数创建一个将作为jstring
返回的字符串。
也许这个链接可以帮到你:
How to return char * aarr= new char[200] from C++ to Java using JNA
当输入字符串不长时,程序运行良好。然而, 当我增加字符串的长度时(这里,我重复&#34;测试 一句话...&#34;事情开始变得奇怪了。我可以看到字符串 是通过C ++程序(成功打印出来),但我收到了 JAVA中的空字符串,这意味着它无法返回字符串。 更重要的是,while循环的时间各不相同 执行(打破循环时打印出不同的计数)。
您目睹的是未定义的行为。从C ++函数返回的指针可能指向包含字符的内存,但不会依赖它,因为您的测试正在向您显示。