如何让JNA读回函数的字符串结果

时间:2013-06-27 10:18:19

标签: jna

public interface Kernel32 extends StdCallLibrary {

    int GetComputerNameW(Memory lpBuffer, IntByReference lpnSize);
}

public class Kernel32Test {

    private static final String THIS_PC_NAME = "tiangao-160";

    private static Kernel32 kernel32;

    @BeforeClass
    public static void setUp() {
    System.setProperty("jna.encoding", "GBK");
    kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
    }

    @AfterClass
    public static void tearDown() {
    System.setProperty("jna.encoding", null);
    }

    @Test
    public void testGetComputerNameW() {
        final Memory lpBuffer = new Memory(1024);
        final IntByReference lpnSize = new IntByReference();

        final int result = kernel32.GetComputerNameW(lpBuffer, lpnSize);

        if (result != 0) {
            throw new IllegalStateException(
            "calling 'GetComputerNameW(lpBuffer, lpnSize)'failed,errorcode:" + result);
        }

        final int bufferSize = lpnSize.getValue();
        System.out.println("value of 'lpnSize':" + bufferSize);
        Assert.assertEquals(THIS_PC_NAME.getBytes().length + 1, bufferSize);

        final String name = lpBuffer.getString(0);
        System.out.println("value of 'lpBuffer':" + name);
        Assert.assertEquals(THIS_PC_NAME, name);
   }
}

offical instructions说使用byte [],char [],Memory或NIO Buffer来映射c本机函数中的char指针。但是我尝试了以上所有,并且String,WString,StringArrays,类扩展了PointType等,所有这些都没用。

输出参数'lpnSize'可以返回校正缓冲区大小,但'lpBuffer'返回'x>'(我认为它是随机存储器)或者无论我映射任何java类型都没有。如果我写了一些'lpBuffer'内存首先,它会在调用本机函数后读取相同的内容。

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

您需要使用Pointer.getString(0, true)来提取GetComputerNameW返回的unicode字符串。

修改

在函数填充结果之前,您还需要使用已初始化的length参数再次调用GetComputerNameW。将相同的IntByReference传回第二次调用,或将IntByReference初始化为Memory缓冲区的大小,以便在第一次调用时写入缓冲区。