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
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.