【问题标题】:Pass pointer or PointerByReference in JNA for pointer argument in C在 JNA 中为 C 中的指针参数传递指针或 PointerByReference
【发布时间】:2020-10-12 18:29:13
【问题描述】:

在 C++ 中,我有以下头文件:

/** Default constructor */
CLPLIB_EXPORT Clp_Simplex *CLP_LINKAGE Clp_newModel(void);

/** Destructor */
CLPLIB_EXPORT void CLP_LINKAGE Clp_deleteModel(Clp_Simplex *model);

尝试使用 JNA 导入它,我假设我必须这样指定它们:

public static native PointerByReference Clp_newModel();

public static native void Clp_deleteModel(Pointer pModel);

这是正确的,应该是Clp_deleteModel(PointerByReference pModel) 吗?奇怪的是,两者似乎都在一个非常简单的测试中工作,尽管前者对我来说更有意义。我认为 JNA 发挥了一些作用。

// option 1
PointerByReference a = Clp_newModel();
ChangeSomthingIntheModel(a,2);
Clp_deleteModel(a.getPointer());
ChangeSomthingIntheModel(a,2); // the JVM signals "illegal memory access here

// option 2
PointerByReference a = Clp_newModel();
ChangeSomthingIntheModel(a,2);
Clp_deleteModel(a); // passing the PointerByReference here! 
ChangeSomthingIntheModel(a,2); // the JVM signals "illegal memory access here

【问题讨论】:

    标签: java pointers dll jna


    【解决方案1】:

    查看 CLP 文档,PointerPointerByReference 似乎都可以在这个简化的示例中使用。

    JNA 中指针的一般表示形式有以下三种:

    • Pointer 类,它有多种方法可以从指向的本机内存中读取和写入。
    • PointerType 类,可以扩展为表示没有其他功能的指针,如果不需要Pointer 功能更好。
    • <something>ByReference 类的集合,它们是指向特定类型对象的指针。

    由于您所做的只是操作指针值,因此以下任何一种方法都可以:更重要的是,您传递的指针对象与您从 Clp_newModel() 检索到的相同类的指针对象(指向你从不处理的东西)。

    注意:您的这部分代码可能没有按照您的预期进行:

    Clp_deleteModel(a.getPointer());
    

    getPointer() 方法返回类的指针,而不是指向的值。在您的使用中,aa.getPointer() 之间没有根本区别(类类型除外)。 (您可能打算使用 a.getValue() 来返回指向的值,这会有所不同,并且可能不是您想要的。)

    目前,您检索PointerByReference,因此您可以访问(通过.getValue())指向的内容,这似乎是CLP_LINKAGE,这似乎不是您将要操作的对象。所以你可以在那里检索一个普通的Pointer(不知道它指向什么)。然后你会将相同的指针传递给Clp-deleteModel(a)

    如果您从不访问指向的值,则可以简单地使用 Pointer,但是,通常更好的做法是限制 API、类型安全和自记录代码来定义扩展 PointerType 的类.在您的情况下,CLPSimplexPtr extends PointerType 将是一个不错的选择。

    如果需要了解返回的指针指向的指针值(CLP_LINKAGE),则使用适当的<whatever>ByReference 扩展ByReference 并实现setValue()getValue() 方法.

    您可能感兴趣,似乎有一个clp-java project 使用BridJ 实现CLP,这是一个Java 到本机的替代库(它使用JNA,但对C++ 进行了许多优化)。对于这两个映射,它们的定义都是 Pointer<CLPSimplex>,如果您在 JNA 中编写它,它将与 CLPSimplexPtr 类对齐——它仍然是一个装饰的普通指针,但是一个类型安全的指针。

    【讨论】:

    • 如果我理解正确的话,JNA 确实有一些魔力。 Pointer 和 PointerByrRference 被视为相同,当且仅当它们被一致地使用 w.r.t。 C 头文件中列出的输入/输出。对于我的实现,我必须更改 clp-java 目前的一些结构。如果我很幸运(如果),我可能会被允许将其推向上游。为了锻炼(我的第一个带有 dll 和 Java 11 的项目),我首先尝试 JNA,而不是 bridgJ :)
    • 没错。引用指针是2个指针,指针本身和它指向的值,恰好也是一个指针。但是如果你从不使用那个指向的指针,你就不需要引用指针。 (但如果你使用它并不会破坏,正如你所展示的那样。)
    • 我认为你最好的 mappipng 是CLPSimplexPtr extends PointerType。只是一个装饰指针,但保持类型安全。
    • 我已经成功实现了后者。不仅因为它是类型安全的,而且还提高了代码的可读性。谢谢。
    猜你喜欢
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    • 2020-08-16
    • 1970-01-01
    • 1970-01-01
    • 2013-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多