如何在Java中获取一个新的指针?

9
如何在JNA中从C调用具有这种方法签名的方法?
int open_device(context *ctx, device **dev, int index);

C方法的最后两行看起来像这样:
*dev = pdev;
return 0;

这个方法中dev的唯一用途就是如此。这意味着我需要将一个空指针的指针传递给该方法,对吗?然后该方法会使用device对象的地址填充空指针,我可以将指向设备的指针传递给其他方法。

我的问题是:这样做是否正确?如果是,我该如何从Java中分配一个新的指针?


根据被接受的答案,我这样做:

Memory p = new Memory(Pointer.SIZE);
Memory p2 = new Memory(Pointer.SIZE);
p.setPointer(0, p2);
nativeLib.open_device(ctx, p, index);
return p2;

只是好奇:你更新的代码是否有效?看起来你设置了 *p = p2,但 C 函数会执行 *p = pdev,从而覆盖该值。 - casablanca
@casablanca:是的,我测试过了,它可以工作。 - thejh
@thejh 你知道如何处理由于指向无效内存地址而引发的 invalidMemoryAccess 异常吗? - AnOldSoul
3个回答

9

看起来JNA Pointer类有setPointergetPointer方法,以允许多重间接引用,并且Memory类实际上是"分配"本机对象的。因此,您应该能够做出这样的事情:(我只是从JNA文档中猜测,我没有测试过这个)

Pointer pDev = new Memory(Pointer.SIZE); // allocate space to hold a pointer value
// pass pDev to open_device
Pointer dev = pDev.getPointer(0);        // retrieve pointer stored at pDev

啊,new Memory(Pointer.SIZE); 看起来就是我需要的,谢谢。 - thejh

0
更好的答案是,您可能需要根据Java字符串长度分配(malloc等)。下面的示例是JNA项目的单元测试。
public void testGetSetStringWithDefaultEncoding() throws Exception {
    final String ENCODING = Native.DEFAULT_ENCODING;
    String VALUE = getName();
    int size = VALUE.getBytes(ENCODING).length+1;
    Memory m = new Memory(size);
    m.setString(0, VALUE);
    assertEquals("Wrong decoded value", VALUE, m.getString(0));
}

-1
Java中没有指针,只有引用。
当你将引用传递给方法时,你不能重新分配它们,因为你是按值传递的。在Java中,所有东西都是按值传递的。
你可以重写这个方法,实例化一个新的设备并返回它,而不是一个int。

3
@duffymo: 我在谈论 JNA Pointers:https://jna.dev.java.net/javadoc/com/sun/jna/Pointer.html - thejh
可以不使用JNA来完成这个操作。你只需要返回实例化的Device对象的新引用,而不是一个int即可。 - duffymo
2
@duffymo:我如何在Java中访问一个C库(libbla.so)而不需要显式使用本地代码? - thejh
@duffymo:在Java中,引用 可以 为空,并且它们可以被重新分配。你可能想到了C ++。此外,在与本地代码交互时,通常使用Java对象来表示本地指针。 - Andy Thomas
你是对的,安迪。现在我意识到我在想C++。我已经纠正了我的回答。 - duffymo
@Andy - 经过再次思考,我认为在讨论中我混淆了语言。我知道Java引用可以为空,而C++则不行。如果OP试图在C++中使用Java模拟指针或引用,那么这些问题必须考虑到。我的表述不太好。 - duffymo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接