3

I have a function in C as:

mySource.c:

int trapdoor(unsigned char keywords[][MAX_SIZE], unsigned int *s, int slen, unsigned char *out, int outlen); 

and where keywords is a array of char arrays (with keywords of different sizes), s is an unsigned int of length slen(EDIT: actually 128-bit=>so value of slen would be 4) and out is the destination pointer where the result of the function is stored and of length outlen(EDIT: 256-bit=>so value of outlen is 32).

Note: Since this is a cryptographic function, I needed the datatypes to be of exact sizes that I mentioned.

And I have to call this function from java using JNI interface. Now what are the equivalent datatypes in java & JNI that I have to pass as parameters to call the trapdoor function in C?

mySource_jni.c:

JNIEXPORT ?? JNICALL Java_proj_trapdoor(JNIEnv *env, jobject obj, ??,  ??, ??, ??, ??, ??);

myJavaSource.java:

private native ?? trapdoor_extraction(??, ??, ??, ??, ??);

I found it from other posts that there is no equivalent to unsigned datatypes in java (correct me if I am wrong).

JoshDM
  • 4,939
  • 7
  • 43
  • 72
annunarcist
  • 1,637
  • 3
  • 20
  • 42
  • It might be simpler to declare the Java native method as `static`, unless you are going to keep `keywords` in a field that is read in the JNI code instead of passing it as a parameter. – Tom Blodget Aug 08 '13 at 21:07
  • 1
    As @JoshDM suggests, you should focus on what the data _is_ before mapping data _types_. You mention keywords, are they strings? If so, what character set and encoding? Are `*s` and `*out` strings too, or just an even number of arbitrary bytes in and any number of arbitrary bytes out? There might be technical limitations in `trapdoor` but the focus should be on how you want to use it in Java. – Tom Blodget Aug 08 '13 at 21:15

3 Answers3

4

It is true that Java does not use unsigned primitive types (except of char which is 16-bit) but you can always use a larger precision.

My suggestion is to produce a method that would make sense in Java no matter if the arguments are signed data types and cast them to unsigned inside your C method.

So I would try to use this first:

int trapdoor(char[][] keywords, int[] s, byte[] out);

Note: You don't need to pass the array lengths since you can get the length of an array in C side using env->GetArrayLength().

  • char[][] is unsigned so even if the Java side passes values greater then a single character you will only use the lower byte thus you will treat it as unsigned char. Otherwise you can use short.

  • int[] you don't mention what type of data it stores. E.g. if it is a key for encryption it would be ok to cast each int to unsigned int. Otherwise use a long[] for this.

  • byte[] I understand that your function will store the values here so this should not matter. Otherwise use a short or an int

I hope it helps

c.s.
  • 4,786
  • 18
  • 32
2

Write your Java Class with native method first, using whatever you expect your data to be when Java receives it.

Then call javah on that Class file.

This will generate header and stub files for use in C++ which you then extend to design your C++ class.


You want to be able to contain all data. Therefore, the largest smallest variable types should be used. As others have noted (I've upvoted them), unsigned int requires a long and unsigned char requires an int, so it breaks down like this:

C                                  | JAVA IN C                    | JAVA
unsigned char keywords[][MAX_SIZE] | jobjectArray of jintArrays   | int[][]
unsigned int *s                    | jlong                        | long
int slen                           | jint                         | int
unsigned char *out                 | jint                         | int
int outlen                         | jint                         | int

Untested prototype, fill-in-the-blanks, do the Java one and use javah:

C:

JNIEXPORT jint JNICALL Java_proj_trapdoor(JNIEnv *env, jobject obj, jobjectArray keywordz,  jlong s, jint slen, jint out, jint outlen);

Java:

private native int trapdoor_extraction(int[][] keywordz, long s, int slen, int out, int outlen);
JoshDM
  • 4,939
  • 7
  • 43
  • 72
  • But I need it in vice-versa way. The definition of the function is in C and my java program does not receive it but has to pass the parameters to call the function from C. – annunarcist Aug 08 '13 at 20:55
  • Convert it to a `jlong` in your code then and pass it as a `long`; expect a `long` on the Java side. http://stackoverflow.com/questions/8012450/jni-converting-unsigned-int-to-jint – JoshDM Aug 08 '13 at 21:20
  • 1
    @annunarcist It depends on where you want to do the type conversion work. Usually, some in Java and some in JNI is best. So design your public Java method with ideal data types for your use in Java. Then design your native method so as little work as possible in JNI is needed. – Tom Blodget Aug 08 '13 at 21:39
2

I am assuming that by '32-byte' you mean '32-bit' and likewise for 16. The reason is, because a number with 32 bytes would actually be a 256-bit number.

These are the bit-counts for each of the Java integers:

byte  ->  8-bit
short ->  16-bit
char  ->  16-bit
int   ->  32-bit
long  ->  64-bit

From this, I believe the Java equivalent would be:

char[][] keywords, int s, short slen, char out, int outlen
Obicere
  • 2,999
  • 3
  • 20
  • 31
  • no, out is of 32-byte(256-bit) length chars and s is a 128-bit number. But isn't char in java 16 bytes size?? – annunarcist Aug 08 '13 at 21:07
  • I believe you are mixing up `byte` and `bit`. There aren't any `256-bit` numbers in C++ or Java. http://compnetworking.about.com/cs/basicnetworking/f/bitsandbytes.htm – Obicere Aug 08 '13 at 21:08