简体   繁体   English

通过JNA调用本地C ++函数的不确定性返回值(字符串类型)

[英]Non-deterministic return values (string type) from calling native C++ functions through JNA

problem description: 问题描述:

My project is JAVA but I want to call a C++ function, which takes a string as input and output another string after process. 我的项目是JAVA,但是我想调用C ++函数,该函数将一个字符串作为输入,并在处理后输出另一个字符串。 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.) 我使用JNA来完成这项工作,而String和char *是从JAVA到C ++的映射类型(在处理过程中,我需要std :: string作为中间类型,详细给出了简单的代码。)

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. 但是,当我增加字符串的长度时(在这里,我将“测试语句...”重复了6次),事情开始变得奇怪。 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. 我可以看到字符串在C ++程序中传递了(成功打印了出来),但是我在JAVA中收到了一个空字符串,这意味着它无法返回该字符串。 What's more, the times of while loop is different on each excution(print out different count when break the loop). 而且,每次执行时while循环的时间都不同(中断循环时打印出不同的计数)。

Then, 然后,

1. What's wrong with the length? 1.长度有什么问题? Is there any limitation in JNA? JNA是否有任何限制?

2. Can I reach my goal and how to pass string in JNA correctly?(BTW, I tried Pointer things, but it doesn't work) 2.我能否达到我的目标以及如何正确地在JNA中传递字符串?(顺便说一句,我尝试了Pointer的操作,但不起作用)

Thanks ahead, here is my code and some enviroment details 谢谢,这是我的代码和一些环境细节

CODE ON C++ SIDE>>>>>>>>>>>test.cpp 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();
}

COMPILE C++ LIBRARY>>>>>>>>> 编译C ++库>>>>>>>>>

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

CODE ON JAVA SIDE>>>>>>>>>>> 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;
            }
        }
    }
}

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)

You have a problem with your C++ code right away. 您马上就遇到了C ++代码问题。 You are returning a pointer to a local std::string that will be destroyed when the function exists. 您正在返回一个指向本地std::string的指针,该指针将在函数存在时被销毁。 Thus you are introducing undefined behavior. 因此,您正在引入未定义的行为。

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. 换句话说,即使应用程序全部是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.
}

The c_str() is tied to the local variable input . c_str()绑定到局部变量input When the function exits, the destructor for input takes place, taking along with it the c_str() that represented the string. 当函数退出时,将发生input的析构函数,并带有代表字符串的c_str()

To fix this, you have to return a string back to Java that will be "alive" after the function returns. 要解决此问题,您必须将字符串返回到Java,该字符串将在函数返回后保持“有效”状态。 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 . 我不知道JNA,但是对于JNI,您可以使用JNI NewStringUTF函数创建一个字符串,该字符串将作为jstring返回。

Maybe this link will help you: 也许此链接将帮助您:

How to return char * aarr= new char[200] from C++ to Java using JNA 如何使用JNA从C ++将char * aarr = new char [200]返回Java

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. 但是,当我增加字符串的长度时(在这里,我将“测试语句...”重复了6次),事情开始变得奇怪。 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. 我可以看到字符串在C ++程序中传递了(成功打印了出来),但是我在JAVA中收到了一个空字符串,这意味着它无法返回该字符串。 What's more, the times of while loop is different on each excution(print out different count when break the loop). 而且,每次执行时while循环的时间都不同(中断循环时打印出不同的计数)。

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. 从您的C ++函数返回的指针可能指向保存字符的内存,但是在您的测试向您展示时,不应依赖它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM