0

私はscanfJNAで関数を使用しようとしています:

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 ランタイム環境によって致命的なエラーが検出されました:

PC=0x000007fefe531435、pid=10168、tid=2964 での EXCEPTION_ACCESS_VIOLATION (0xc0000005)

JRE バージョン: 7.0_03-b05 Java VM: Java HotSpot(TM) 64 ビット サーバー VM (22.1-b02 混合モード windows-amd64 圧縮 oops) 問題のあるフレーム: C [msvcrt.dll+0x61435]

コア ダンプの書き込みに失敗しました。ミニダンプは、クライアント バージョンの Windows では既定で有効になっていません。

詳細情報を含むエラー レポート ファイルは、*****\URC Lab\hs_err_pid10168.log として保存されます。

バグ レポートを提出したい場合は、次のサイトにアクセスしてください: http://bugreport.sun.com/bugreport/crash.jspJava 仮想マシンの外部でネイティブ コードでクラッシュが発生しました。バグを報告する場所については、問題のあるフレームを参照してください。

プログラム出力:

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

エラーが発生するのはなぜですか?どうすれば修正できますか?

4

2 に答える 2

2

のマニュアルページを注意深く読んでくださいscanf。各 varargs 引数は、スキャンされたアイテムが書き込まれるメモリへのアドレス (つまり、ポインタ) でなければなりません。

JavaStringは不変オブジェクトです。つまり、書き込めません。

書き込み可能なバッファには、プリミティブ配列 (例: 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");

    }
}
于 2013-04-30T10:51:47.843 に答える
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およびputs関数を使用してテキストをコンソールにすぐに出力しました。

于 2016-10-05T18:57:25.973 に答える