2013-03-11 3 views
3

Я пытаюсь вызвать функцию C++ из Java через JNA. Я хочу передать строку и вернуть строку. Это делается с использованием параметра in и параметра out. Я использую PointerByReference для представления параметра char**. Вызов C++ работает, но PointerByReference имеет значение null после вызова.PointerByReference не возвращает значение

Я основывал свой код на документах PointerByReference. Любые идеи, что я делаю неправильно?

Я добавил операторы печати на C++, чтобы убедиться, что он не устанавливает указатель на нуль, и это определенно не так. Поэтому некоторые из моих использования JNA должны быть ошибочными. Но что?

C++ код

void processRequest(char* input, char** output, int* outputLength) 
{ 

    // Variable output size from processInput 

    std::string sOutput = processInput(input); 


    char* results = new char[sOutput.length() + 1]; 

    strncpy(results, sOutput.c_str(), sOutput.length()); 

    results[sOutput.length()] = '\0'; 


    output = &results; 

    outputLength = new int(strlen(results) + 1); 

} 

Java код

Что называют Явы так:

public class RunRequestT1 { 
    private static final Logger log = LoggerFactory.getLogger(MyLibWrapperImpl.class); 

    static boolean envVarsSetupDone = false; 

    static interface MyLib extends Library { 

     MyLib INSTANCE = (MyLib) Native.loadLibrary("N:\\sys1\\sys1_dist\\MyLib\\MyLib9.8.Q.P3.G15.T\\bin\\MyLib.dll", MyLib.class); 

     public void processRequest(String request, PointerByReference bufp, IntByReference lenp); 

     public void clearMemoryPtr(PointerByReference bufp, IntByReference lenp); 
    } 

    public static void main(String[] args) throws IOException { 

     System.out.println("sys1: Reading request"); 
     String request = FileUtils.readFileToString(new File("C:\\dev\\prj\\single-request.xml"), "UTF-8"); 

     System.out.println("sys1: Pricing request"); 
     String response = processRequest(request); 

     System.out.println(response); 

    } 

    public static String processRequest(String request) { 

     System.out.println("sys1: prepare args"); 
     // code based on https://github.com/twall/jna/blob/master/www/ByRefArguments.md 
     PointerByReference bufp = new PointerByReference(); 
     IntByReference lenp = new IntByReference(); 

     System.out.println("sys1: making call"); 
     MyLib.INSTANCE.processRequest(request, bufp, lenp); 

     System.out.println("reading response"); 
     System.out.println("bufp: " + bufp.getValue()); 
     System.out.println("lenp: " + lenp.getValue()); 
     Pointer p = bufp.getValue(); 
     byte[] buffer = p.getByteArray(0, lenp.getValue()); 
     String response = Native.toString(buffer); 
     //String response = p.getString(0); 

     // de-allocate memory buffer 
     System.out.println("cleaning memory"); 
     MyLib.INSTANCE.clearMemoryPtr(bufp, lenp); 
     return response; 
    } 
} 

Stdout

И когда я это называю, я получаю результаты, как это:

sys1: Reading request 
sys1: Pricing request 
sys1: prepare args 
sys1: making call 
reading response 
bufp: null 
lenp: 0 
Exception in thread "main" java.lang.NullPointerException 
    at com.calyon.gcm.MyLibwrapper.main.RunRequestT1.priceRequest() 
    at com.calyon.gcm.MyLibwrapper.main.RunRequestT1.main() 

Я пытался держать его минимальным, и в самом деле существует не так много происходит.

Я проверил с версии ЮНА 3,4 и 3,5

+0

Вместо ЮНА, вы могли бы рассмотреть возможность использования [JavaCPP] (http://code.google.com/p/javacpp/), который может напрямую вызвать функции C++. –

ответ

3

Вместо того, чтобы выделить новый указатель для вашей длины «возврата», вам нужно написать в существующий указатель, например,

*outputLength = strlen(results) + 1; 

Вы также должны написать указателю буфер, который был дан, а не просто присвоения нового значения в локальном арг:

*output = results; 
Смежные вопросы