Function scanf with JNA

半世苍凉 提交于 2019-12-08 14:08:54

问题


I'm trying to use the scanf function with 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);
}
}

I'm new to this and I also read a lot about JNA. But I can't really figure out how to use it. The printf function works without problems.

This is the error I get, when I start it and after I wrote something to the console.

A fatal error has been detected by the Java Runtime Environment:

EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000007fefe531435, pid=10168, tid=2964

JRE version: 7.0_03-b05 Java VM: Java HotSpot(TM) 64-Bit Server VM (22.1-b02 mixed mode windows-amd64 compressed oops) Problematic frame: C [msvcrt.dll+0x61435]

Failed to write core dump. Minidumps are not enabled by default on client versions of Windows

An error report file with more information is saved as: *****\URC Lab\hs_err_pid10168.log

If you would like to submit a bug report, please visit: http://bugreport.sun.com/bugreport/crash.jsp The crash happened outside the Java Virtual Machine in native code. See problematic frame for where to report the bug.

Program output:

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

Why do I get the error, and how can I fix it?


回答1:


Read carefully the man page for scanf. Each varargs argument must be the address (i.e. a pointer) to memory where the scanned item may be written.

Java String is an immutable object. That means you can't write to it.

Writable buffers include primitive arrays (e.g. byte[]), JNA Memory, or an NIO buffer. In this case I'd recommend using Memory of sufficient size, then use its getString() method to extract the native NUL-terminated C string as a Java String.

For scanning other types, JNA provides ByReference and its subclasses, which provides the functionality of the common native &var notation.

An example, as @Gary suggested:

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");

    }
}



回答2:


    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");

    }
}

I found this solution to fix the "scanf" Invalid memory access problem and immediately prints the text to the console using the printf and puts functions.



来源:https://stackoverflow.com/questions/16296566/function-scanf-with-jna

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!