【问题标题】:Function scanf with JNA带有 JNA 的函数 scanf
【发布时间】:2016-11-30 23:57:57
【问题描述】:

我正在尝试将 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 (0xc0000005) 在 pc=0x000007fefe531435, pid=10168, tid=2964

JRE 版本:7.0_03-b05 Java VM:Java HotSpot(TM) 64 位服务器 VM (22.1-b02 混合模式 windows-amd64 压缩 oops) 有问题的框架: 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

为什么会出现错误,我该如何解决?

【问题讨论】:

    标签: java scanf jna


    【解决方案1】:

    仔细阅读scanf 的手册页。每个 varargs 参数必须是指向可写入扫描项目的内存的地址(即指针)。

    Java String 是一个不可变对象。这意味着你不能写它。

    可写缓冲区包括原始数组(例如byte[])、JNA Memory 或 NIO 缓冲区。在这种情况下,我建议使用足够大小的Memory,然后使用其getString() 方法将本机NUL 终止的C 字符串提取为Java String

    对于扫描其他类型,JNA 提供了ByReference 及其子类,它们提供了常见的原生&amp;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");
    
        }
    }
    

    【讨论】:

      【解决方案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");
      
          }
      }
      

      我找到了解决“scanf”无效内存访问问题的解决方案,并立即使用 printf 和 puts 函数将文本打印到控制台。

      【讨论】:

      • 欢迎来到 Stack Overflow!尽管此代码可能有助于解决问题,但它并没有解释 why 和/或 如何 回答问题。提供这种额外的背景将显着提高其长期价值。请edit您的答案添加解释,包括适用的限制和假设。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-09
      • 1970-01-01
      相关资源
      最近更新 更多