I want to use Java JNA to send an array of doubles to C, C will process data and write something into the array of doubles. Then I could use java to read it out. Btw C code is in a shared lib.
But My code does not work.
C function I am calling:
int swe_calc_ut(double *xx);
Java code to call that function:
(already establish the connection with C shared lib, the .so file
That part has been tested and work fine. So ignore that part.)
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.ptr.*;
import com.sun.jna.Pointer;
// declare the C function
int swe_calc_ut(DoubleByReference xx);
// call the C function
DoubleByReference xx = new DoubleByReference();
swe_calc_ut(xx);
Error:
malloc(): invalid size (unsorted)
Process finished with exit code 134 (interrupted by signal 6: SIGABRT)
I guess it's related to pointer operation cause arrays are all pointer in C. But don't really know what to code.
DoubleByReference only allocates space for a single (8-byte) double value, but you've specified an array.
JNA can handle primitive arrays just fine without any special treatment. See this example at JNA's PointersAndArrays doc:
// Original C declarations
void fill_buffer(int *buf, int len);
void fill_buffer(int buf[], int len); // same thing with array syntax
// Equivalent JNA mapping
void fill_buffer(int[] buf, int len);
So in your case, you could simply call
// declare the C function
int swe_calc_ut(double[] xx);
// call the C function
double[] xx = new double[size];
swe_calc_ut(xx);
Note that all you're really passing under the hood is a pointer to the start of the array, and there is no size information given. Either the API for the function specifies the size of the array, or there must be a way for you to communicate that size; otherwise the C side won't know where the array ends.
You could also pass the pointer by allocating a buffer using new Memory(Native.LONG_DOUBLE_SIZE * arraySize) and setting/getting the double array with the associated Pointer getters.
Related
I am trying to free the memory of t_data which is assigned as dummy variable. (The code is below). Now as soon as I free t_data the program throws a heap corruption error but instead if I copy all the stuff from body to a new memory for t_data, everything works fine. The delete code is called somewhere down the line in another class method (not shown here), it just uses t_Data pointer to delete the memory.
jshortArray val = (jshortArray)(m_pJVMInstance->m_pEnv->CallStaticObjectMethod(m_imageJ_cls, method_id, arr, (jint)t, (jint)c));
jsize len = m_pJVMInstance->m_pEnv->GetArrayLength(val);
jshort* body = m_pJVMInstance->m_pEnv->GetShortArrayElements(val, 0);
unsigned short int* dummy = reinterpret_cast<unsigned short int*>(body);
//t_data = dummy; //NOTE: Once you free t_data later exception is thrown.
t_data = new unsigned short int[len];
for (int i = 0; i < len; i++) {
unsigned short int test = *(body + i);
*((unsigned short int*)t_data + i) = test;
}
I am trying to figure out a way where I dont have to run the for loop to copy the body data to t_data and still be able to free the memory. (The for loop takes too much time for big images.)
What Michael said was correct and that indeed solved the problem. Referring to his comment:
Yes, definitely don't call free or delete on the pointer returned by GetShortArrayElements, because you don't know what GetShortArrayElements did internally. It might not have allocated any memory at all. Some implementations just pin the Java array to avoid having it moved by the GC, and then returns a pointer to the actual Java array contents. Just call ReleaseShortArrayElements when you're done with the pointer. – Michael
I am using JNA to write a Java interface for a C++ written DLL for control of a small device.
While translating data types I came across
const char*** someVariable
Can someone please explain to me what this means and how can it be recreated in Java?
I have read up on pointers and I am using the JNA documentation to map C++ types to Java but I cannot find a reference to a type with three asterisks at the end.
Should this be interpreted as a pointer to a String array?
if you know the concept of pointers,
const char*** means it is a triple pointer, so you can think of it this way:
const char***--->const char**--->const char*--->const char
So yes it can be interpreted as a pointer to a string array, because a string array can be interpreted as a double pointer.
let's say a is an array of strings:
const char *a[15];
In this case **a would give you the first char of the first string in a.
you can declare:
const char ***b = &a;
in this case ***b would give you the first char of the first string in a.
The most likely interpretation is that you are expected to pass in the address of a pointer, and on return, the pointer will be an array of C strings.
That's not the only possible interpretation, but probably the most likely one. This is especially true if the native signature also asks for a pointer to integer into which it will write the length of the returned array.
To use this from JNA:
PointerByReference pref = new PointerByReference();
IntegerByReference iref = new IntegerByReference();
nativeLib.call(pref, iref);
String[] strings = pref.getValue().getStringArray(0, iref.getValue());
If no length is specified, JNA will look for a NULL value marking the end of the string array.
I am having some difficulty in understanding how to write the below piece of code using String or char[] in Java.
void xyz(char *a, int startIndex, int endIndex)
{
int j;
for (j = startIndex; j <= endIndex; j++)
{
doThis((a+startIndex), (a+j));
xyz(a, startIndex+1, endIndex);
}
}
Here char *a points to the starting location of the char name[]
The above are just some random functions, but I just want the logic of how to use char* and character index char[] in Java
Based on the rephrased question from the comment thread:
You cannot change the characters of a Java String. If you need to modify a sequence of characters, use StringBuilder, which supports setCharAt(int, char), insert(int, char), and append(char). You can use new StringBuilder(myString) to convert a String to a StringBuilder, and stringBuilder.toString() to convert back.
This is perfectly legit Java code -- it's not code smelly, it's just the way you work with mutable character sequences.
A char* in C is, as you noted, pointing to the start of your character array (which is how C manages Strings).
In C the size of a char is one byte, and pointers always point to the start of a byte. Your C String is an array of characters, so adding 1 to a pointer moves the start of your string right by one character.
That means that the C code:
char *a;
// Set the String here
a = a + 1;
translates in Java to something like:
String a;
// Set the String here
a = a.substring(1);
or if you are using a char array:
char[] a;
// Set the array contents here
char[] copyTo = new char[a.length];
System.arraycopy(a, 1, copyTo, 0, a.length);
a = copyTo;
Java will be a bit more careful of protecting you that C will be though. For instance, if you have a zero length string, the C code has the potential to either segfault (crashing the application) or give you a gibberish string full of memory junk (then, eventually, crash the application), whereas the Java code will throw an exception (normally an IndexOutOfBoundsException) which you can, hopefully, handle cleanly.
Remember though, that String in Java are immutable. You cannot change them, you can only create new Strings. Fortunately, String has several built in functions which allow you to do a lot of the standard actions, like replace part of the String with another and return the result. A character array is mutable, and you can change the characters within them, but you will lose a lot of the nice benefits you get from using the proper String class.
Simple Answer:
You can't do exactly that. Java is pass by reference only. You don't have access to memory location information, so you can't do arithmetic with it.
Longer Answer:
It looks like you are passing in a string for manipulation. You have several options to simulate that.
You can convert the string to an array of characters and then pass in a char[]. If your manipulations are not any sort of standard string operation and completely custom this is probably what you need to do. Keep in mind that you can't change the size of the array passed in, nor can you have a point at a new array after the function completes. (again, only pass by value). Only the values of the existing elements of the array can be modified.
You can pass in the String and use the String methods, such as subString() (which your begin and end indexes seem to suggest, but this may not meet your needs. Note that strings are immutable however, and you can only get a result out via the return statement.
If you really need to modify the contents of the object passed in you can pass a StringBuilder, StringBuffer or CharBuffer object and modify away.
There's a hack that can also be used to circumvent pass by reference, but it's poor style except in special situations. Pass in an array of whatever you need to modify, so in this case an array of array of characters would allow you to set a new sub-array, and effectively acheive pass by reference, but try not to do this :)
If your method modifies the values you cant use String as that is immutable, you can use StringBuilder instead.
If your methods already rely on char arrays and you need the offsets you can use a CharBuffer to wrap an array. It does not support String operations but supports views for sub ranges, which seems to be what you use in the doThis() method.
I am trying to use a C API in java using JNI. I'm not a C programmer...
Here is the C "object" I have to convert : char *tab[10]
First, I'm not sure what it means : is it a pointer to a tab of char, or a tab of pointers to char ? (and is there any difference ?).
Then, what would the equivalent java object ?
char * tab[10] is pointer to an array of chars (points on first element).
Here is JNI API:
http://download.oracle.com/javase/1.5.0/docs/guide/jni/spec/jniTOC.html
Type equivalent for "C char" in JNI is jchar - in java it is "char" primitive type;
Possibilities of What you can do having array of "C chars" are: copy it into existand String object in java OR into java primitive char array.
Usefull link:
http://download.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html#array_operations
The 2nd way is may looks like that:
you pass a java char array into JNI call or create new java array from C code with New<PrimitiveType>Array function. However you will end with pointer to array in java.
They copy your C chars into java's one:
jEnv->ReleaseCharArrayElements(javaCharArray, C_CharArray, JNI_COMMIT);
where jEnv - is java enviroment, passing through JNI call. In case u have a pointer u may need to dereference it like *C_CharArray. I think thats may work out.
It's (most likely) an array of 10 strings, and so would be modeled directly as:
String[] tab = new String[10];
It's also possible that it's an array of character buffers, so you might use a StringBuilder instead of a String. And remember, Java arrays are objects in their own right and know their size so that information is not attached to the type (unlike in C, where array sizes are type characteristics).
I'd not expect to have direct transfer of the type/value through JNI; you'll need some conversion glue code in there.
I have a C structure that is sent over some intermediate networks and gets received over a serial link by a java code. The Java code gives me a byte array that I now want to repackage it as the original structure. Now if the receive code was in C, this was simple. Is there any simple way to repackage a byte[] in java to a C struct. I have minimal experience in java but this doesnt appear to be a common problem or solved in any FAQ that I could find.
FYI the C struct is
struct data {
uint8_t moteID;
uint8_t status; //block or not
uint16_t tc_1;
uint16_t tc_2;
uint16_t panelTemp; //board temp
uint16_t epoch#;
uint16_t count; //pkt seq since the start of epoch
uint16_t TEG_v;
int16_t TEG_c;
}data;
I would recommend that you send the numbers across the wire in network byte order all the time. This eliminates the problems of:
Compiler specific word boundary generation for your structure.
Byte order specific to your hardware (both sending and receiving).
Also, Java's numbers are always stored in network-byte-order no matter the platform that you run Java upon (the JVM spec requires a specific byte order).
A very good class for extracting bits from a stream is java.nio.ByteBuffer, which can wrap arbitrary byte arrays; not just those coming from a I/O class in java.nio. You really should not hand code your own extraction of primitive values if at all possible (i.e. bit shifting and so forth) since it is easy to get this wrong, the code is the same for every instance of the same type, and there are plenty of standard classes that provide this for you.
For example:
public class Data {
private byte moteId;
private byte status;
private short tc_1;
private short tc_2;
//...etc...
private int tc_2_as_int;
private Data() {
// empty
}
public static Data createFromBytes(byte[] bytes) throws IOException {
final Data data = new Data();
final ByteBuffer buf = ByteBuffer.wrap(bytes);
// If needed...
//buf.order(ByteOrder.LITTLE_ENDIAN);
data.moteId = buf.get();
data.status = buf.get();
data.tc_1 = buf.getShort();
data.tc_2 = buf.getShort();
// ...extract other fields here
// Example to convert unsigned short to a positive int
data.tc_2_as_int = buf.getShort() & 0xffff;
return data;
}
}
Now, to create one, just call Data.createFromBytes(byteArray).
Note that Java does not have unsigned integer variables, but these will be retrieved with the exact same bit pattern. So anything where the high-order bit is not set will be exactly the same when used. You will need to deal with the high-order bit if you expected that in your unsigned numbers. Sometimes this means storing the value in the next larger integer type (byte -> short; short -> int; int -> long).
Edit: Updated the example to show how to convert a short (16-bit signed) to an int (32-bit signed) with the unsigned value with tc_2_as_int.
Note also that if you cannot change the byte-order and it is not in network order, then java.nio.ByteBuffer can still serve you here with buf.order(ByteOrder.LITTLE_ENDIAN); before retrieving the values.
This can be difficult to do when sending from C to C.
If you have a data struct, cast it so that you end up with an array of bytes/chars and then you just blindly send it you can sometimes end up with big problems decoding it on the other end.
This is because sometimes the compiler has decided to optimize the way that the data is packed in the struct, so in raw bytes it may not look exactly how you expect it would look based on how you code it.
It really depends on the compiler!
There are compiler pragma's you can use to make packing unoptimized. See C/C++ Preprocessor Reference - pack
The other problem is the 32/64-bit bit problem if you just use "int", and "long" without specifying the number of bytes... but you have done that :-)
Unfortunately, Java doesnt really have structs... but it represents the same information in classes.
What I recommend is that you make a class that consists of your variables, and just make a custom unpacking function that will pull the bytes out from the received packet (after you have checked its correctness after transfer) and then load them in to the class.
e.g. You have a data class like
class Data
{
public int moteID;
public int status; //block or not
public int tc_1;
public int tc_2;
}
Then when you receive a byte array, you can do something like this
Data convertBytesToData(byte[] dataToConvert)
{
Data d = Data();
d.moteId = (int)dataToConvert[0];
d.status = (int)dataToConvert[1];
d.tc_1 = ((int)dataToConvert[2] << 8) + dataTocConvert[3]; // unpacking 16-bits
d.tc_2 = ((int)dataToConvert[4] << 8) + dataTocConvert[5]; // unpacking 16-bits
}
I might have the 16-bit unpacking the wrong way around, it depends on the endian of your C system, but you'll be able to play around and see if its right or not.
I havent played with Java for sometime, but hopefully there might be byte[] to int functions built in these days.
I know there are for C# anyway.
With all this in mind, if you are not doing high data rate transfers, definately look at JSON and Protocol Buffers!
Assuming you have control over both ends of the link, rather than sending raw data you might be better off going for an encoding that C and Java can both use. Look at either JSON or Protocol Buffers.
What you are trying to do is problematic for a couple of reasons:
Different C implementations will represent uint16_t (and int16_t) values in different ways. In some cases, the most significant byte will be first when the struct is laid out in memory. In other cases, the least significant byte will.
Different C compilers may pack the fields of the struct differently. So it is possible (for example) that the fields have been reordered or padding may have been added.
So what this all means is that you have to figure out exactly the struct is laid out ... and just hope that this doesn't change when / if you change C compilers or C target platform.
Having said that, I could not find a Java library for decoding arbitrary binary data streams that allows you to select "endian-ness". The DataInputStream and DataOutputStream classes may be the answer, but they are explicitly defined to send/expect the high order byte first. If your data comes the other way around you will need to do some Java bit bashing to fix it.
EDIT : actually (as #Kevin Brock points out) java.nio.ByteBuffer allows you to specify the endian-ness when fetching various data types from a binary buffer.