带有JNA的函数scanf

我正在尝试使用JNA的scanf函数:

 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.jsphttp://bugreport.sun.com/bugreport/crash.jsp崩溃发生在Java虚拟机之外的本机代码中。 查看有问题的框架,了解在哪里报告错误。

节目输出:

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

为什么我会收到错误,我该如何解决?

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

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

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

对于扫描其他类型,JNA提供了ByReference及其子类,它提供了常见的native &var表示法的function。

一个例子,正如@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"); } } 
  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函数将文本打印到控制台。