简体   繁体   English

在 JNA 中将指针或 PointerByReference 传递给 C 中的指针参数

[英]Pass pointer or PointerByReference in JNA for pointer argument in C

In C++ I have the following header file:在 C++ 中,我有以下头文件:

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

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

Trying to import this with JNA, I assume that I have to specify them as such:尝试使用 JNA 导入它,我假设我必须这样指定它们:

public static native PointerByReference Clp_newModel();

public static native void Clp_deleteModel(Pointer pModel);

Is this correct, of should it be Clp_deleteModel(PointerByReference pModel) ?这是正确的,应该是Clp_deleteModel(PointerByReference pModel)吗? Strangely, both seem to work in a very simple test, though the former does make more sense to me.奇怪的是,两者似乎都在一个非常简单的测试中工作,尽管前者对我来说更有意义。 I assume that JNA does some of its magic.我认为 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

Looking at the CLP documentation, it appears that either Pointer or PointerByReference would work in this simplified example.查看 CLP 文档,似乎PointerPointerByReference可以在这个简化的示例中工作。

There are three general representations of pointers in JNA: JNA中指针的三种一般表示:

  • The Pointer class, which has several methods for reading and writing from the pointed-to native memory. Pointer类,它有多种方法可以从指向的本机内存中读取和写入。
  • The PointerType class, which can be extended to represent a pointer with no other functionality, better if you don't need Pointer functionality. PointerType类,可以扩展为表示没有其他功能的指针,如果您不需要Pointer功能则更好。
  • The collection of <something>ByReference classes, which are pointers to specific types of objects. <something>ByReference类的集合,它们是指向特定类型对象的指针。

Since all you're ever doing is manipulating the pointer value, any of these would work: The more important point is that you pass a pointer object of the identical class that you retrieved from Clp_newModel() which is a pointer (to something you never deal with).由于您所做的只是操作指针值,因此其中任何一个都可以工作:更重要的一点是,您传递从Clp_newModel()检索到的相同类的指针对象,该对象是一个指针(指向您从未使用过的指针Clp_newModel()处理)。

Note: this part of your code may not be doing what you expect it to do:注意:这部分代码可能没有按照您的预期执行:

Clp_deleteModel(a.getPointer());

The getPointer() method returns the pointer of the class, not the value being pointed to. getPointer()方法返回类的指针,而不是指向的值。 There's no fundamental difference (except class type) between a and a.getPointer() in your usage.在您的使用中aa.getPointer()之间没有根本区别(类类型除外)。 (You might be meaning to use a.getValue() which returns the pointed-to value, which would be different, and probably not what you want.) (您可能打算使用a.getValue()返回指向的值,这会有所不同,而且可能不是您想要的。)

Currently you retrieve a PointerByReference so you have access (via .getValue() ) to what's being pointed to, which appears to be a CLP_LINKAGE , which doesn't appear to be an object you'll ever manipulate.当前,您检索PointerByReference以便您可以访问(通过.getValue() )指向的内容,它似乎是CLP_LINKAGE ,它似乎不是您将要操作的对象。 So you could retrieve a plain Pointer there (without knowing what it points to) instead.所以你可以在那里检索一个普通的Pointer (不知道它指向什么)。 And you would pass that same pointer to Clp-deleteModel(a) .您可以将相同的指针传递给Clp-deleteModel(a)

If you are never accessing the pointed-to value, you can simply use Pointer , however, it's generally a better practice for restricting the API, type safety, and self-documenting code to define a class extending PointerType .如果您从不访问指向的值,则可以简单地使用Pointer ,但是,通常更好的做法是限制 API、类型安全和自文档化代码以定义扩展PointerType的类。 In your case, CLPSimplexPtr extends PointerType would be a good choice.在您的情况下, CLPSimplexPtr extends PointerType将是一个不错的选择。

If there is a need to understand the pointer value (the CLP_LINKAGE ) that the returned poniter is being pointed at, then use the appropriate <whatever>ByReference extending ByReference and implementing the setValue() and getValue() methods.如果需要了解返回的指针所指向的指针值( CLP_LINKAGE ),则使用适当的<whatever>ByReference扩展ByReference并实现setValue()getValue()方法。

Of possible interest to you, it seems there is a clp-java project that implements CLP using BridJ , an alternative Java-to-native library (which uses JNA but has many optimizations for C++).您可能感兴趣,似乎有一个clp-java项目使用BridJ实现CLPBridJ是一个替代的 Java 到本机库(它使用 JNA,但对 C++ 进行了许多优化)。 Their definition is Pointer<CLPSimplex> for both mappings, which would align with a CLPSimplexPtr class if you wrote it in JNA -- it's still a decorated plain pointer, but a type-safe one.它们的定义是Pointer<CLPSimplex>用于两个映射,如果您在 JNA 中编写它,它将与CLPSimplexPtr类对齐——它仍然是一个装饰的普通指针,但是一个类型安全的指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM