0

I am trying to port the libbmp library to Android as a shared library. My Android project contains under the jni folder the following:

  1. Android.mk (top Android makefile)

    LOCAL_PATH := $(call my-dir)
    include $(call all-subdir-makefiles)
    
  2. libbmp

    • Android.mk

      LOCAL_PATH := $(call my-dir)
      include $(CLEAR_VARS)
      LOCAL_MODULE    := libbmp
      LOCAL_SRC_FILES := bmpfile.c
      include $(BUILD_SHARED_LIBRARY)`
      
    • bmpfile.c (extracted from libbmp-0.1.3)

    • bmpfile.h (extracted from libbmp-0.1.3)
  3. libbmptest

    • Android.mk

      LOCAL_PATH := $(call my-dir)
      include $(CLEAR_VARS)
      LOCAL_MODULE     := PortingShared
      LOCAL_C_INCLUDES := $(LOCAL_PATH)/../libbmp/
      LOCAL_SRC_FILES := PortingShared.c
      LOCAL_SHARED_LIBRARIES := libbmp
      LOCAL_LDLIBS := -llog
      include $(BUILD_SHARED_LIBRARY)`
      
    • PortingShared.c (makes use of the libbmp library in naCreateABmp function)

      #include <jni.h>
      
      #ifndef _Included_cookbook_chapter8_portingshared_MainActivity
      #define _Included_cookbook_chapter8_portingshared_MainActivity
      #ifdef __cplusplus
      extern "C" {
      #endif
      /*
       * Class:     cookbook_chapter8_portingshared_MainActivity
       * Method:    naCreateABmp
       * Signature: (III)V
       */
      JNIEXPORT void JNICALL Java_cookbook_chapter8_portingshared_MainActivity_naCreateABmp
        (JNIEnv *env, jclass clazz, jint width, jint height, jint depth);
      
      bmpfile_t *bmp;
      int i, j;
      rgb_pixel_t pixel = {128, 64, 0, 0};
      
      for (i = 10, j = 10; j < height; ++i, ++j) {
          bmp_set_pixel(bmp, i, j, pixel);
          pixel.red++;
          pixel.green++;
          pixel.blue++;
          bmp_set_pixel(bmp, i + 1, j, pixel);
          bmp_set_pixel(bmp, i, j + 1, pixel);
      }
      
      bmp_save(bmp, "/sdcard/test_shared.bmp");
      bmp_destroy(bmp);
      
      
      
      #ifdef __cplusplus
      }
      #endif
      #endif
      

I must also mention that my MainActivity.java is loading the libbmp and PortingShared libraries as well as calling the native function naCreateABMP

public static native void naCreateABmp(int width, int height, int depth);

static {
    System.loadLibrary("bmp");
     System.loadLibrary("PortingShared");
}

However, when I try to build it with the ndk-build command, I get the errors:

PortingShared/jni/libbmptest/PortingShared.c:18:1: error: unknown type name 'bmpfile_t'
PortingShared/jni/libbmptest/PortingShared.c:20:1: error: unknown type name 'rgb_pixel_t'
PortingShared/jni/libbmptest/PortingShared.c:20:1: warning: excess elements in scalar initializer [enabled by default]
PortingShared/jni/libbmptest/PortingShared.c:20:1: warning: (near initialization for 'pixel') [enabled by default]
PortingShared/jni/libbmptest/PortingShared.c:20:1: warning: excess elements in scalar initializer [enabled by default]
PortingShared/jni/libbmptest/PortingShared.c:20:1: warning: (near initialization for 'pixel') [enabled by default]
PortingShared/jni/libbmptest/PortingShared.c:20:1: warning: excess elements in scalar initializer [enabled by default]
PortingShared/jni/libbmptest/PortingShared.c:20:1: warning: (near initialization for 'pixel') [enabled by default]
PortingShared/jni/libbmptest/PortingShared.c:22:1: error: expected identifier or '(' before 'for'
PortingShared/jni/libbmptest/PortingShared.c:22:24: error: expected '=', ',', ';', 'asm' or '__attribute__' before '<' token
PortingShared/jni/libbmptest/PortingShared.c:22:34: error: expected identifier or '(' before '++' token
PortingShared/jni/libbmptest/PortingShared.c:31:15: error: expected ')' before string constant
PortingShared/jni/libbmptest/PortingShared.c:32:1: warning: data definition has no type or storage class [enabled by default]
PortingShared/jni/libbmptest/PortingShared.c:32:1: warning: parameter names (without types) in function declaration [enabled by default]
make: *** [PortingShared/obj/local/armeabi/objs/PortingShared/PortingShared.o] Error 1
Fabian N.
  • 3,807
  • 2
  • 23
  • 46
magmablade
  • 23
  • 6
  • Wild guess: I think you miss a `LOCAL_C_INCLUDE = ` in your second (2) makefile, before the `include $(BUILD_SHARED_LIBRARY)`. I suspect that specifying it in the third one isn't the correct way. – JBL Sep 05 '14 at 21:46
  • @JBL I'm not entirely sure about what you mean, but all the `libbmp` files are already located in the same module, i.e `libbmp.h` and `libbmp.c` are already located under `libbmp` which contains the makefile without the `LOCAL_C_INCLUDE` – magmablade Sep 05 '14 at 23:28
  • I mean that you should list your include directory (which contains the `bmpfile.h`) between `LOCAL_SRC_FILES := bmpfile.c` and `include $(BUILD_SHARED_LIBRARY)`. This makefile should contain a `LOCAL_C_INCLUDE` variable I think, following the advice of [this developer's guide](http://www.kandroid.org/ndk/docs/ANDROID-MK.html): _LOCAL_C_INCLUDE: An optional list of paths, relative to the NDK *root* directory, which will be appended to the include search path when compiling all sources_. – JBL Sep 06 '14 at 08:18
  • @JBL Alright, I've tried it but it doesn't seem to solve the problem. So what I've done is that I've evaluated `LOCAL_C_INCLUDES := $(LOCAL_PATH)` because the `LOCAL_PATH` is the path to the `libbmp` folder which does contain the `libbmp.h` – magmablade Sep 06 '14 at 10:15
  • Mmmh, wait but... in the cpp file you pasted... where's the include for `bmpfile.h`? – JBL Sep 06 '14 at 10:44
  • The `bmpfile.h` is included in the compiled shared library, so following the `Android.mk` from `libbmp` there will be generated a `libbmp.so`. Moreover, in the `Android.mk` file from the `libbmptest`, i.e the folder with the `PortingShared.c` I specifically mention that the `.so` that will be compiled out of this will depend on `libbmp.so`, i.e `LOCAL_SHARED_LIBRARIES := libbmp` and if you have a look on the `java` code, I include the `libbmp` library before the `PortingShared` one. – magmablade Sep 06 '14 at 11:59
  • Yes, but what I mean is that your source file is probably missing a `#include "bmpfile.h"` at some point. Look at your error message, the compiler _don't know the type bmpfile_! The shared library contains the definition for the functions, but your source file must at some point know about the declarations. – JBL Sep 06 '14 at 14:18
  • The `bmpfile.h` is included in the `bmpfile.c` which is compiled as a `.so` and should be used by the `PortingShared.c` to compile the `PortingShared.so`. – magmablade Sep 06 '14 at 21:30
  • Yes. Now is `bmpfile.h` included in `PortingShared.c`? That's where it's missing. – JBL Sep 07 '14 at 16:11
  • Alright, that appears to have solved the problem. Thank you! – magmablade Sep 08 '14 at 13:00
  • @JBL Although this is fixed and everything is working properly, I'd have one more question. Why is that I still have to explicitly say `#include "` if I declare `LOCAL_SHARED_LIBRARIES := libbmp`. I mean to me it already seems like I've let `PortingShared.c` know about the existance of `libbmp` and where to get the methods from. – magmablade Sep 08 '14 at 14:34
  • No, it's not how C++ works. There's two steps during the build that matters. First, there's compilation, where the compiler take your `.c` file, and parse it to see if it's correct C++. And for that he must know every names that it finds in it (hence the need for the `.h` include). Then, he'll output object files. These files are then _linked_ with the libraries (static case), or the executable must find dynamic libraries somewhere (dynamic case), often next to him (.so on linux, .dll on Windows). These libs must then contains the appropriate functions. But the C file must know the names. – JBL Sep 08 '14 at 14:41
  • For further reading, I encourage you to read [**this**](http://stackoverflow.com/questions/6264249/how-does-the-compilation-linking-process-work). – JBL Sep 08 '14 at 14:43
  • @JBL Alright, much appreciated. – magmablade Sep 08 '14 at 21:10

0 Answers0