與JNA

2013-04-30 36 views
0

我試圖使用scanf功能與JNA功能scanf函數:與JNA

package importDLLs; 

import com.sun.jna.Library; 
import com.sun.jna.Native; 

public class JNATest { 

public interface CLibrary extends Library { 
    CLibrary clib = (CLibrary) Native.loadLibrary("msvcrt", CLibrary.class); 

    void printf(String format, Object... args); 
    int sprintf(byte[] speicher, String format, Object...args); 
    int scanf (String format, Object... args1); 
} 


public static void main(String[] args) { 
    CLibrary.clib.printf("Hello World"); 
    String test= null; 
    args = new String[2]; 
    args[0]="This is a test"; 
    args[1]="and another one"; 
    for (int i = 0; i < args.length; i++){ 
     CLibrary.clib.printf("\nArgument %d : %s",i, args[ i ]); 
    } 

    CLibrary.clib.printf("\nBitte Namen eingeben"); 
    CLibrary.clib.scanf("%s", test); 
    CLibrary.clib.printf("\nyour name is %s",test); 
} 
} 

我是新來的這一點,我也讀了很多關於JNA。但我無法弄清楚如何使用它。 printf函數沒有問題。

這是我得到的錯誤,當我啓動它,並在我寫了一些東西后,控制檯。

已經由Java運行時環境中檢測到致命錯誤:

EXCEPTION_ACCESS_VIOLATION(0000005)中的PC = 0x000007fefe531435, PID = 10168,TID = 2964

JRE版本:7.0_03-B05 Java虛擬機:爪哇熱點(TM)64位服務器VM (22.1-B02混合模式窗口-AMD64壓縮糟糕)有問題的幀: C [MSVCRT.DLL + 0x61435]

無法寫入核心轉儲。小型轉儲默認情況下不啓用在Windows

的 客戶端版本包含更多信息的錯誤報告文件保存爲: ***** \ URC實驗室\ hs_err_pid10168.log

如果你想提交一個錯誤報告,請訪問: http://bugreport.sun.com/bugreport/crash.jsp崩潰發生在本地代碼中Java虛擬機之外的 。看有問題的框架 報告錯誤的地方。

程序輸出:

Hello World 
Argument 0 : This is a test 
Argument 1 : and another one 
your name is 

爲什麼我得到的錯誤,以及如何解決呢?

回答

1

請仔細閱讀scanf的手冊頁。每個變量參數都必須是可以寫入掃描項目的內存地址(即指針)。

Java String是一個不可變的對象。這意味着你不能寫信給它。

可寫緩衝區包括基元數組(例如byte[]),JNA Memory或NIO緩衝區。在這種情況下,我建議使用足夠大小的Memory,然後使用其getString()方法將本地NUL終止的C字符串提取爲Java String

對於掃描其他類型,JNA提供ByReference及其子類,它提供了常見的本機&var表示法的功能。

一個例子,作爲@Gary建議:

import com.sun.jna.Library; 
import com.sun.jna.Native; 
import com.sun.jna.Platform; 
import com.sun.jna.Pointer; 

public interface JNAApiInterface extends Library { 
    JNAApiInterface INSTANCE = (JNAApiInterface) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), JNAApiInterface.class); 
    Pointer __iob_func(); 

    int sizeOfFileStructure = Platform.is64Bit() ? 48 : 32; 
    Pointer stdout = JNAApiInterface.INSTANCE.__iob_func().share(sizeOfFileStructure); 

    void printf(String format, Object... args); 
    int sprintf(byte[] buffer, String format, Object... args); 
    int scanf(String format, Object... args); 
    int fflush (Pointer stream); 
    int puts(String format) ; 
    int fprintf(Pointer stream, String format, Object...args) ; 
    void setbuf(Pointer stream, String buffer) ; 
} 

import com.sun.jna.Memory; 
import com.sun.jna.platform.win32.Kernel32; 

public class JNABucket { 
    public static void main(String args[]) { 

     JNAApiInterface jnaLib = JNAApiInterface.INSTANCE; 
     Kernel32 klib = Kernel32.INSTANCE; 
     Memory userName = new Memory(256); 

     jnaLib.setbuf(jnaLib.stdout, null); 
     jnaLib.printf("Hello World"); 

     for (int i = 0; i < args.length; i++) { 
      jnaLib.printf("\nArgument %d : %s", i, args[i]); 
     } 

     jnaLib.puts("\nPlease Enter Your Name:\n"); 

     jnaLib.scanf("%s", userName); 
     jnaLib.printf("\nYour name is: %s", userName); 

     jnaLib.fprintf(jnaLib.stdout, "\nThis is a Test"); 

    } 
} 
1
import com.sun.jna.Library; 
    import com.sun.jna.Native; 
    import com.sun.jna.Platform; 
    import com.sun.jna.Pointer; 

    public interface JNAApiInterface extends Library { 
     JNAApiInterface INSTANCE = (JNAApiInterface) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), JNAApiInterface.class); 
     Pointer __iob_func(); 

     int sizeOfFileStructure = Platform.is64Bit() ? 48 : 32; 
     Pointer stdout = JNAApiInterface.INSTANCE.__iob_func().share(sizeOfFileStructure); 

     void printf(String format, Object... args); 
     int sprintf(byte[] buffer, String format, Object... args); 
     int scanf(String format, Object... args); 
     int fflush (Pointer stream); 
     int puts(String format) ; 
     int fprintf(Pointer stream, String format, Object...args) ; 
     void setbuf(Pointer stream, String buffer) ; 
    } 


    import com.sun.jna.Memory; 
import com.sun.jna.platform.win32.Kernel32; 

public class JNABucket { 
    public static void main(String args[]) { 

     JNAApiInterface jnaLib = JNAApiInterface.INSTANCE; 
     Kernel32 klib = Kernel32.INSTANCE; 
     Memory testName = new Memory(256); 

     jnaLib.setbuf(jnaLib.stdout, null); 
     jnaLib.printf("Hello World"); 
     for (int i = 0; i < args.length; i++) { 
      jnaLib.printf("\nArgument %d : %s", i, args[i]); 
     } 

     jnaLib.puts("\nPlease Enter Your Name:\n"); 
     jnaLib.scanf("%s", testName); 
     jnaLib.printf("\nYour name is: %s", testName); 
     jnaLib.fprintf(jnaLib.stdout, "\nthis is a Test"); 

    } 
} 

我發現這個解決方案來解決「scanf函數」無效的內存訪問問題並立即使用printf的打印文本到控制檯,並把功能。

+0

歡迎來到Stack Overflow!雖然這段代碼可能有助於解決這個問題,但它並沒有解釋_why_和/或_how_它是如何回答這個問題的。提供這種附加背景將顯着提高其長期價值。請[編輯]您的答案以添加解釋,包括適用的限制和假設。 – 2016-10-05 20:26:52