Reputation: 77
In C++ I have the following header file:
/** 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:
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)
? 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.
// 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
Upvotes: 1
Views: 1648
Reputation: 9091
Looking at the CLP documentation, it appears that either Pointer
or PointerByReference
would work in this simplified example.
There are three general representations of pointers in JNA:
Pointer
class, which has several methods for reading and writing from the pointed-to native memory.PointerType
class, which can be extended to represent a pointer with no other functionality, better if you don't need Pointer
functionality.<something>ByReference
classes, which are pointers to specific types of objects.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).
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. There's no fundamental difference (except class type) between a
and a.getPointer()
in your usage. (You might be meaning to use a.getValue()
which returns the pointed-to value, which would be different, and probably not what you want.)
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. So you could retrieve a plain Pointer
there (without knowing what it points to) instead. And you would pass that same pointer to 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
. In your case, CLPSimplexPtr extends PointerType
would be a good choice.
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.
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++). 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.
Upvotes: 2