在 JNA 中使用 printf 和 scanf 的问题
Problems using printf and scanf with JNA
我写了一些 Java JNA 初学者代码。我构建它没有编译错误。
我从 here 下载 JNA 5.6。
我只看到此命令的输出:
System.out.println( "Hello" );
为什么不起作用?
package layout;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
interface JNAApiInterface extends Library {
@SuppressWarnings( "deprecation")
JNAApiInterface INSTANCE = (JNAApiInterface) Native.loadLibrary(
Platform.isWindows() ? "msvcrt" : "c", JNAApiInterface.class);
void printf( String format, Object... args );
int sprintf( byte[] buffer, String format, Object... args );
int scanf( String format, Object... args );
}
public class JNA01 {
public static void main( String args[] ) {
System.out.println( "Hello" );
JNAApiInterface jnaLib = JNAApiInterface.INSTANCE;
jnaLib.printf( "Hello World" );
String testName = null;
jnaLib.printf( "Please Enter Your Name: \n" );
jnaLib.scanf( "%s", testName );
jnaLib.printf( "\nYour name is %s", testName );
}
}
您的 JNA 映射是正确的,但您没有正确使用本机函数。
scanf()
函数要求您为缓冲区分配内存以填充 testName
值,但您向它传递了一个具有空值的不可变 String
!
该程序打印第一个 Hello
,实际上已经打印了 Hello WorldPlease Enter Your Name:
,但是您的 IDE 可能还没有显示此标准输出,因为它正在等待 scanf()
的输入].如果您实际输入了一个值,您会遇到分段错误,因为它会尝试将您输入的名称写入未分配的内存!
要解决这个问题,您需要分配一个缓冲区来填充。将字节数组分配给 testNum
,JNA 将自动为其保留分配的内存。然后使用 Native.toString()
.
解码字节
这个版本的主循环有效:
public static void main(String args[]) {
System.out.println("Hello");
JNAApiInterface jnaLib = JNAApiInterface.INSTANCE;
jnaLib.printf("Hello World\n");
// this is dangerous as you don't control how long user input is
// but for learning it's fine, you will crash with longer names
byte[] testName = new byte[100];
jnaLib.printf("Please Enter Your Name: \n");
jnaLib.scanf("%s", testName);
jnaLib.printf("\nYour name is %s", Native.toString(testName));
}
我写了一些 Java JNA 初学者代码。我构建它没有编译错误。
我从 here 下载 JNA 5.6。
我只看到此命令的输出:
System.out.println( "Hello" );
为什么不起作用?
package layout;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
interface JNAApiInterface extends Library {
@SuppressWarnings( "deprecation")
JNAApiInterface INSTANCE = (JNAApiInterface) Native.loadLibrary(
Platform.isWindows() ? "msvcrt" : "c", JNAApiInterface.class);
void printf( String format, Object... args );
int sprintf( byte[] buffer, String format, Object... args );
int scanf( String format, Object... args );
}
public class JNA01 {
public static void main( String args[] ) {
System.out.println( "Hello" );
JNAApiInterface jnaLib = JNAApiInterface.INSTANCE;
jnaLib.printf( "Hello World" );
String testName = null;
jnaLib.printf( "Please Enter Your Name: \n" );
jnaLib.scanf( "%s", testName );
jnaLib.printf( "\nYour name is %s", testName );
}
}
您的 JNA 映射是正确的,但您没有正确使用本机函数。
scanf()
函数要求您为缓冲区分配内存以填充 testName
值,但您向它传递了一个具有空值的不可变 String
!
该程序打印第一个 Hello
,实际上已经打印了 Hello WorldPlease Enter Your Name:
,但是您的 IDE 可能还没有显示此标准输出,因为它正在等待 scanf()
的输入].如果您实际输入了一个值,您会遇到分段错误,因为它会尝试将您输入的名称写入未分配的内存!
要解决这个问题,您需要分配一个缓冲区来填充。将字节数组分配给 testNum
,JNA 将自动为其保留分配的内存。然后使用 Native.toString()
.
这个版本的主循环有效:
public static void main(String args[]) {
System.out.println("Hello");
JNAApiInterface jnaLib = JNAApiInterface.INSTANCE;
jnaLib.printf("Hello World\n");
// this is dangerous as you don't control how long user input is
// but for learning it's fine, you will crash with longer names
byte[] testName = new byte[100];
jnaLib.printf("Please Enter Your Name: \n");
jnaLib.scanf("%s", testName);
jnaLib.printf("\nYour name is %s", Native.toString(testName));
}