gpt4 book ai didi

java - 通过 JNA 调用 native C++ 函数的非确定性返回值(字符串类型)

转载 作者:行者123 更新时间:2023-11-30 05:42:58 27 4
gpt4 key购买 nike

问题描述:

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

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

然后,

<强>1。长度有什么问题? JNA有什么限制吗?

<强>2。我能达到我的目标吗?如何正确地在 JNA 中传递字符串?(顺便说一句,我试过指针的东西,但它不起作用)

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

C++ 端的>>>>>>>>>>>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();
}

编译 C++ 库>>>>>>>>>

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

JAVA 端的>>>>>>>>>>

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

运行细节>>>>>>>>>>>>>

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 的指针,该指针将在函数存在时被销毁。因此,您正在引入未定义的行为。

换句话说,即使应用程序都是 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() 绑定(bind)到局部变量input。当函数退出时,input 的析构函数发生,同时带走表示字符串的 c_str()

要解决此问题,您必须向 Java 返回一个字符串,该字符串在函数返回后将“存活”。我不知道 JNA,但对于 JNI,您可以使用 JNI NewStringUTF 函数创建一个字符串,该字符串将作为 jstring 返回。

也许这个链接可以帮到你:

How to return char * aarr= new char[200] from C++ to Java using JNA

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++ 函数返回的指针可能 指向保存字符的内存,但不应该依赖它,正如您的测试所显示的那样。

关于java - 通过 JNA 调用 native C++ 函数的非确定性返回值(字符串类型),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30414872/

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