Saturday, February 9, 2013

Implementing the Native Function On C/C++

Now that the makefiles are defined, we need to complete the C implementation by creating fibonacci.c and calling the newly implemented function from the glue layer. Because the function implemented in fibonacci.c needs to be declared before it can be called, a new header file is also created. You will also need to add fibonacci.c to the list of files to compile in Android.mk.
 Implementation of the New Function in fibonacci.c

#include “fibonacci.h” 
uint64_t recursive (unsigned int n) {
     if (n > 1) return recursive(n-2) + recursive(n-1);  
 return n;
}
 Calling the Function From the Glue Layer
#include “com_apress_proandroid_Fibonacci.h”
#include “fibonacci.h” 
/*  * Class:       com_apress_proandroid_Fibonacci 
* Method:    recursiveNative 
* Signature: (I)J  */
jlong JNICALL
 Java_com_apress_proandroid_Fibonacci_recursiveNative  
(JNIEnv *env, jclass clazz, jint n) {    
return recursive(n);
}
Header File fibonacci.h
#ifndef _FIBONACCI_H_
#define _FIBONACCI_H_ 
#include <stdint.h> 
extern uint64_t recursive (unsigned int n); 
#endif

NOTE:  "Make sure you use the right types in your C/C++ code as jlong is 64-bit. Use well- defined types such as uint64_t or int32_t when size matters. "


Some may argue that using multiple files creates unnecessary complexity, and everything could be implemented in the glue layer, that is, in a single file instead of three or four (fibonacci.h, fibonacci.c, com_apress_proandroid_Fibonacci.c, and possibly even com_apress_proandroid_Fibonacci.h). While this is technically feasible, it is not recommended. Doing this would tightly couple the glue layer with the implementation of the native function, making it harder to reuse the code in a non-Java application. For example, you may want to reuse the same header and C/C++ files in an iOS application. Keep the glue layer JNI-specific, and JNI-specific only. 
While you may also be tempted to remove the inclusion of the JNI header file, keeping it as it guarantees your functions are consistent with what is defined in the Java layer (assuming you remember to recreate the header file with the javah tool whenever there is a relevant change in Java).
Listing 2–10. All Three Files Combined Into One
#include “com_apress_proandroid_Fibonacci.h”
#include <stdint.h> 
static uint64_t recursive (unsigned int n) {
    if (n > 1) return recursive(n-2) + recursive(n-1);  
 return n;

/*  * Class:       com_apress_proandroid_Fibonacci 
* Method:    recursiveNative 
* Signature: (I)J
 */
 jlong JNICALL
 Java_com_apress_proandroid_Fibonacci_recursiveNative
  (JNIEnv *env, jclass clazz, jint n)
{
     return recursive(n);
}

No comments:

Post a Comment