JNA: Pointer to char** - java

I own the next C function:
int fillWithNames(const char*** names, int *n);
which I convert to java using JNA proceeding like this:
public interface PlayersLibrary extends Library {
PlayersLibrary INSTANCE = (PlayersLibrary) Native.loadLibrary("player", PlayersLibrary.class);
int fillWithNames(PointerByReference names, IntByReference n);
}
How could I print the Strings that this method returns in names?
I want to do something like this:
PlayersLibrary.INSTANCE.fillWithNames(names, n);
Pointer first = names.getValue(); // char**
String a = first.getPointer(0).getValue() // char*
System.out.println(a);
but in this case, names.getValue() returns null and I donĀ“t know what to do
What can I do to solve this problem?

Use names.getValue().getStringArray(0, n.getValue()]).
I'm inferring that the n parameter is telling the callee how many names to fill in. getStringArray() will convert consecutive pointer values in memory into strings until it encounters a NULL value; if your callee doesn't terminate with a NULL pointer you'll need to explicitly tell it how many pointers to read (ostensibly the n parameter in the call to fillWithNames()).
EDIT
So the length does indeed come back in the n parameter. If the callee writes a zero to that parameter, then it's telling you it has no names (which would by why you get a null back in the other parameter).

Class PointerByReference
Represents a reference to a pointer to native data. In C notation, void**.
Also, see SO: PointerByReference not returning value.

Related

Delete value for previously assigned int field [duplicate]

Can an int be null in Java?
For example:
int data = check(Node root);
if ( data == null ) {
// do something
} else {
// do something
}
My goal is to write a function which returns an int. Said int is stored in the height of a node, and if the node is not present, it will be null, and I'll need to check that.
I am doing this for homework but this specific part is not part of the homework, it just helps me get through what I am doing.
Thanks for the comments, but it seems very few people have actually read what's under the code, I was asking how else I can accomplish this goal; it was easy to figure out that it doesn't work.
int can't be null, but Integer can. You need to be careful when unboxing null Integers since this can cause a lot of confusion and head scratching!
e.g. this:
int a = object.getA(); // getA returns a null Integer
will give you a NullPointerException, despite object not being null!
To follow up on your question, if you want to indicate the absence of a value, I would investigate java.util.Optional<Integer>
No. Only object references can be null, not primitives.
A great way to find out:
public static void main(String args[]) {
int i = null;
}
Try to compile.
In Java, int is a primitive type and it is not considered an object. Only objects can have a null value. So the answer to your question is no, it can't be null. But it's not that simple, because there are objects that represent most primitive types.
The class Integer represents an int value, but it can hold a null value. Depending on your check method, you could be returning an int or an Integer.
This behavior is different from some more purely object oriented languages like Ruby, where even "primitive" things like ints are considered objects.
Along with all above answer i would like to add this point too.
For primitive types,we have fixed memory size i.e for int we have 4 bytes and char we have 2 bytes. And null is used only for objects because there memory size is not fixed.
So by default we have,
int a=0;
and not
int a=null;
Same with other primitive types and hence null is only used for objects and not for primitive types.
The code won't even compile. Only an fullworthy Object can be null, like Integer. Here's a basic example to show when you can test for null:
Integer data = check(Node root);
if ( data == null ) {
// do something
} else {
// do something
}
On the other hand, if check() is declared to return int, it can never be null and the whole if-else block is then superfluous.
int data = check(Node root);
// do something
Autoboxing problems doesn't apply here as well when check() is declared to return int. If it had returned Integer, then you may risk NullPointerException when assigning it to an int instead of Integer. Assigning it as an Integer and using the if-else block would then indeed have been mandatory.
To learn more about autoboxing, check this Sun guide.
instead of declaring as int i declare it as Integer i then we can do i=null;
Integer i;
i=null;
Integer object would be best. If you must use primitives you can use a value that does not exist in your use case. Negative height does not exist for people, so
public int getHeight(String name){
if(map.containsKey(name)){
return map.get(name);
}else{
return -1;
}
}
No, but int[] can be.
int[] hayhay = null; //: allowed (int[] is reference type)
int hayno = null; //: error (int is primitive type)
//: Message: incompatible types:
//: <null> cannot be converted to int
As #Glen mentioned in a comment, you basically have two ways around this:
use an "out of bound" value. For instance, if "data" can never be negative in normal use, return a negative value to indicate it's invalid.
Use an Integer. Just make sure the "check" method returns an Integer, and you assign it to an Integer not an int. Because if an "int" gets involved along the way, the automatic boxing and unboxing can cause problems.
Check for null in your check() method and return an invalid value such as -1 or zero if null. Then the check would be for that value rather than passing the null along. This would be a normal thing to do in old time 'C'.
Any Primitive data type like int,boolean, or float etc can't store the null(lateral),since java has provided Wrapper class for storing the same like int to Integer,boolean to Boolean.
Eg: Integer i=null;
An int is not null, it may be 0 if not initialized. If you want an integer to be able to be null, you need to use Integer instead of int . primitives don't have null value. default have for an int is 0.
Data Type / Default Value (for fields)
int ------------------ 0
long ---------------- 0L
float ---------------- 0.0f
double ------------- 0.0d
char --------------- '\u0000'
String --------------- null
boolean ------------ false
Since you ask for another way to accomplish your goal, I suggest you use a wrapper class:
new Integer(null);
I'm no expert, but I do believe that the null equivalent for an int is 0.
For example, if you make an int[], each slot contains 0 as opposed to null, unless you set it to something else.
In some situations, this may be of use.

Pointer to pointer equivalent in java [duplicate]

This question already has answers here:
C++ Pointers to Pointers in Java
(5 answers)
Closed 7 years ago.
For last some day I am learning Java while I have some knowledge in C. Now I am trying to convert code written in C to a Java code. There I found a pointer to pointer (pptr)variable declaration like this -
int n;
int *ptr;
int **pptr;
n = 13;
ptr = &n;
pptr = &ptr;
As far as I know, in Java there is no pointer type variable. My question is there any way to represent pptr or anything equivalent of pptr in Java?
Let's look at some of the use cases for multiple indirection in C, and see how they apply to Java.
Use Case #1: you want a function or method to change the value of a pointer or reference parameter such that it points to a new object, and have that change reflected in the caller.
In C, that would look something like this:
void foo( T **p )
{
*p = new_value(); // update the thing p points to
}
void bar( void )
{
T *var; // for any type T
foo( &var ); // foo will set var to point somewhere else
}
var is a pointer to something, and we want the function foo to change var such that it points to something else. Since C passes all function arguments by value, if we want foo to update var, we must pass a pointer to var, giving us a pointer to pointer type in foo.
Java doesn't expose operations on pointer types (no unary & address-of or * indirection operators), so we can't do this directly. We'd have to wrap the reference we want to change in another reference type and pass that wrapper type to the method, and even then I'm not sure it would do the same thing as the C code above:
public class thing
{
// attributes
}
public class thingWrapper {
{
public thing t;
}
public void pointToNewThing( thingWrapper tw )
{
tw.t = newThing();
}
public void bar()
{
thing t = new thing();
...
thingWrapper tw = new thingWrapper();
tw.t = t;
pointToNewThing( tw );
t = tw.t;
...
}
Use Case #2: you want to allocate a multi-dimensional array in a piecemeal fashion, rather than in a single operation. This is useful if you want a "jagged" array (where the number of elements in each row isn't uniform) or if you're trying to allocate a lot of memory and don't have a single available block large enough for the whole thing.
In C, you'd do something like
T **arr = malloc( N * sizeof *arr );
if ( arr )
{
for ( int i = 0; i < N; i++ )
{
arr[i] = malloc( M * sizeof *arr[i] );
}
}
because C arrays are not "first class" objects, and cannot be manipulated and assigned directly, so you have to do this through pointers.
Java treats arrays completely differently such that you don't need to do the pointer-to-pointer dance at all:
T arr[][] = new arr[N];
for ( i = 0; i < N; i++ )
{
arr[i] = new arr[M];
}
I can't think of other use cases off the top of my head, but that should give you a flavor of how you'd translate the C concept to Java.
The short answer is yes. But first, a lesson in Java...
In Java, whenever you use objects, pointers are involved. If you have an object, the variable that "holds" that object is actually a pointer to that object. So if you are working with objects, you are already using pointers.
Now for primitive data types (e.g., integers, chars, or floating point numbers), Java does not use pointers, though. So if you want pointers for primitive data types, you need to use a wrapper class, such as Integer, which effectively promotes the value to an object.
Note, however, that the default wrapper classes are immutable.
If you want double-pointers (a pointer to a pointer) or triple pointers, you will need to create custom wrapper classes, like an ObjectWrapper class, that allows you to set up an arbitrary number of objects each pointing to (or "holding") the next.
What you can do is create an int array even with a size of 1 this way when you access the array it will always refer to the same place in memory as far as your programming is concerned.

convert Integer to int

I have an Integer value of variable as below:
Integer programNumber= ........
I took the program number as Integer type. However in my other class, I want to check whether this variable, programNumber, equals variable which is the type of int.
To sum up, I want to convert the variable of the of Integer to int primitive value.
I used programno.intValue() but it doesn't work.
Thanks in advance.
I have a two class, BasvuruKisi and Program. the code snippet is below:
BasvuruKisi bsvkisi = (BasvuruKisi) (this.getHibernateTemplate().find("from BasvuruKisi bsv where bsv.basvuruNo=?", basvuruNumaralari.get(i))).get(0);
if (bsvkisi != null) {
int yetkiVarmi = 0;
Integer programno= bsvkisi.getProgramId();
List array =
this.getHibernateTemplate().find("from Program p where p.id=?", programno.intValue());
but
this.getHibernateTemplate().find("from Program p where p.id=?", programno.intValue());
this one doesn't work. return firstly, no table or view is available despite available and then returns null pointer exception.
thanks
The variable name in the initialization block says programNumber, but the variable in the method call is programno. Which is it?
Using the wrong variable name shouldn't give you a null pointer exception, unless you have another variable named programno defined somewhere.
Whatever the variable name is, make sure you initialize it before you get the intValue.
Validate programNumber is null or not?
If the value is null, it throws Exception.
Integer programNumber= null;
System.out.println(programNumber.intValue());

SWIG, can I assign a value to a char** passed from Java to C

I have a C API that looks like this:
int my_function(char** assign_me_a_string);
I basically need the native code to tell me a value. If I do:
char* my_function();
It works fine. I get a String in return that I can use in Java. However I would prefer to use the first approach since all my functions returns an int by default (status value).
I have tried to use various.i and this typemap:
%apply char **STRING_ARRAY { char **assign_me_a_string }
Doing this I get a String[] generated for the Java API. Then I try to use it by:
String[] myStringToAssign = new String[1];
my_function(myStringToAssign);
But this seems to just crash.
So, is there a proper way to assign a value to a Java String from inside the C code? I am not trying to use an array, I just need to be able to dereference the char** and assign it a string in the native code that can then be used as a String object in Java.
Java String is immutable and references are passed by value so the following will not do what you think (pure Java):
// java:
void someFunction(String yourString) {yourString = "bye";}
void test() {
String test = "hi";
someFunction(test);
System.out.println(test); // prints "hi", not "bye"!
}
(For more on this, see for example Passing a String by Reference in Java?). Needless to say you can't do it using JNI either.
Look at section 24.10.5 of SWIG 2.0 docs: it shows how you could do this for char** via a typemap. However the typemap there would have to be modified to check the char* array on exit (the freearg typemap, perhaps) to replace the contents of the String[]. Your function could assume only one item.
Alternately you could wrap your Java String in a class, which will get passed by reference; however you again would have to use a typemap to copy any changes that have been made into the data member.
Probably the easiest is to provide a helper function that swaps the status code and string:
// C/C++ lib: the function you'd like to export but can't:
int my_function(char*& ) {
val = new char[20];
...put stuff in val, don't forget the terminating \0 char...
return status;
}
Create wrapper:
// SWIG .i file: an "adapter" function, Java gives you no choice:
%inline %{
char* my_function(int& err) {
char * val;
err = my_function(val);
return val;
%}
SWIG will take care of copying the char* to the returned String:
// From Java you can then do:
int status;
String result = my_function(status);
System.out.println(result);
No, Java Strings are immutable and cannot be assigned not even through JNI.

Passing array as an argument: C and Java

Before I ask my question, I will note that I know:
In C, we can call a method by value as well by reference
In Java, we can only call a method by value ( when we pass an Object, we are passing the value of the object reference not the object reference itself )
In C and Java context, there is a difference between pointers and reference.
Now to the question:
Consider an array:
arr = {1,2,3,4,5} //len =5
In C, I can do the following two things:
foo(arr, len);
bar (arr+ 2, len -2);
Function definitions:
foo(int *a, int l) {
...
printf("%d", &a[0]; //prints 1
...
}
bar (int *a, int l){
printf("%d", &a[0]; //prints 3
...
}
As we can see array a in function bar starts with the value 3, as it contains the address of arr[2](the original array). This is a neat way of passing arrays in C, if we want to treat a sub-array as a new array with starting index 0.
I was wondering if same can be achieved in Java not withstanding that the following call has different meanings in C and Java:
foo(arr);
yes, just add a parameter int off or use the IntBuffer class.
void foo(int[] a,int off, int l) {
...
System.out.printf("%d", a[off]; //prints 1
...
...
}
f(a,2,l);
void foo(IntBuffer a,int l){
System.out.printf("%d",a.get(0));
}
IntBuffer buffer = IntBuffer.wrap(a,2,a.length-2);
foo(buffer,l);
If your question is about whether you can address the elements of the array by doing pointer arithmetic like in arr + 2, then the answer is no.
However, you can achieve the same effect by passing in the array and the position where you want start reading the array.
The underlying structure of the array in java has an extra element at the head that indicates it's length. So your original array would be {len, 1, 2, 3, 4, 5} as stored by the JVM. This is done to keep java 'safe' from out of index operations on the array. This also makes it almost impossible to do pointer arithmetic in java.
To do something like this in java you would typically use some sort of Buffer class to wrap your array.
Java lacks native slicing functions (as the implicit one you have in C regarding the start of the array or the explicit ones you have in a few modern languages) but it's easy to build your own class wrapping an array, an index and a length if you need it.
The idea is the same when you pass arrays in C and Java.
In Java, all that are passed for objects are references to them, namely pointers. In Java, you never say: A *a = new A(); you just write A a = new A(); The lack of * is the difference. Otherwise, A behaves exactly like a pointer.
Primitive variables are passed by value.

Categories