1

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
0

1 Answer 1

2

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:

  • The Pointer class, which has several methods for reading and writing from the pointed-to native memory.
  • The PointerType class, which can be extended to represent a pointer with no other functionality, better if you don't need Pointer functionality.
  • The collection of <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.

Sign up to request clarification or add additional context in comments.

4 Comments

If I understand correctly, JNA does do some magic. Pointer and PointerByrRference are treated as the same, if- and only if- they are used consistently w.r.t. the input/outputs listed in the C header file. For my implementation I have to change some of the structure that clp-java has as of now. If I' m lucky (big if) I might be allowed to push this upstream. For the sake of exercise (my first project with a dll and Java 11) I am trying JNA first rahter than bridgJ :)
That's correct. Pointer by reference is 2 pointers, the pointer itself, and the value it's pointing to, which happens to also be a pointer. But if you never use that pointed-to pointer, you don't need pointer by reference. (But it doesn't break if you use it, as you've demonstrated.)
I think your best mappipng is a CLPSimplexPtr extends PointerType. Just a decorated pointer, but keeps type safety.
I have successfully implemented the latter. Not only because it is type-safe, but it also improves the readability of the code. Merci.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.