Using SWIG in combination with the Android NDK

963 views
Skip to first unread message

Maarten Wijnants

unread,
Jul 6, 2009, 10:40:13 AM7/6/09
to android-ndk
Hi all,

I have been experimenting with using native code on the Android
platform for a few days now, and I am still facing a number of
problems.

Let's start with my successes so far. I have tested the sample
applications included in the Android NDK, and they work perfectly. I
have also already been able to write a small C library and invoke its
methods on Android through the NDK build tools and the .mk build
files.

My goal however is to access the functionality of an (existing) C++
library on the Android platform. The library contains a number of
classes and I would like to be able to use the library on Android as
on other platforms (i.e. win32 and unix). Instead of completely
converting the code to Java, I would like to use it as a native
library and invoke its functionality through JNI.

To the best of my knowledge, the most straightforward way to do so
would be to use SWIG (the Simplified Wrapper and Interface Generator,
http://www.swig.org/). Please correct me if I am wrong in this
statement as I am far from an expert in the field of Java programming.
Using SWIG allows programmers to work with the classes implemented in C
++ libraries in other languages, including Java. I have tested this on
win32 and it worked perfectly.

On Android however, I have up till now not been able to achieve the
same outcome. It appears to me the problem is that the implementation
of the native methods cannot be located in the native library. I could
however be wrong in this assessment.

Here is my source code. First there is the "native" C++ class, which
is implemented in files newtestclass.h and newtestclass.cpp as
follows:


newtestclass.h
-------------------

#ifndef NEWTESTCLASS_H
#define NEWTESTCLASS_H

class NewTestClass
{
public:
NewTestClass();
~NewTestClass();

void setX(const int x);
int getX() const;
private:
int m_x;
};

#endif // NEWTESTCLASS_H


newtestclass.cpp
----------------------

#include "newtestclass.h"


NewTestClass::NewTestClass() : m_x(0)
{

}

NewTestClass::~NewTestClass()
{

}

void NewTestClass::setX(const int x)
{
m_x = x;
}

int NewTestClass::getX() const
{
return m_x;
}


As you can see this is pretty straightforward C++ code, to make sure
the problems are not being caused by advanced C++ constructs.

As instructed in the SWIG tutorial, I have written a SWIG interface
file for this class. The contents is as follows:


newtestclass.i
-------------------

%module newtestclassmodule
%{
#include "newtestclass.h"
%}

%include "newtestclass.h"


Again very simple. On this interface class, I invoke the swig tool as
follows:

swig -c++ -o newtestclass_wrap.cpp -package com.example.newtest -java
newtestclass.i

which generates the file newtestclass_wrap.cpp. If desired/needed, I
can provide the contents of this file. Files newtestclass.cpp and
newtestclass_wrap.cpp are added to the LOCAL_SRC_FILES variable of my
Android.mk build file. Compiling the native library using the NDK make
tool succeeds and generates the library libnewtest.so (as the name of
my NDK module is "newtest").

Besides the newtestclass_wrap.cpp file, the swig tool also generates a
number of .java files which contain the Java implementation of the
NewTestClass class. As is expected, each memberfunction of this Java
class simply invokes its corresponding native method. This
implementation seems correct to me.

Finally, I attempt to use the Java NewTestClass inside the onCreate
method of an Android activity class as follows:

public class RunMe extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

System.loadLibrary("newtest");

NewTestClass ntc = new NewTestClass();

TextView tv = new TextView(this);
tv.setText("Returned value = " + ntc.getX());
setContentView(tv);
}
}

I compile and run the Android activity class using the Eclipse ADT
plug-in. When executing the Android application, LogCat output
suggests the libnewtest.so library is loaded successfully. However I
do get some warnings:

D/dalvikvm( 2027): Trying to load lib /data/data/com.example.newtest/
lib/libnewtest.so 0x43597078
D/dalvikvm( 2027): Added shared lib /data/data/com.example.newtest/lib/
libnewtest.so 0x43597078
D/dalvikvm( 2027): No JNI_OnLoad found in /data/data/
com.example.newtest/lib/libnewtest.so 0x43597078
D/dalvikvm( 2027): +++ not scanning '/system/lib/libwebcore.so' for
'new_NewTestClass' (wrong CL)
D/dalvikvm( 2027): +++ not scanning '/system/lib/libmedia_jni.so' for
'new_NewTestClass' (wrong CL)
D/dalvikvm( 2027): +++ not scanning '/system/lib/libwebcore.so' for
'NewTestClass_getX' (wrong CL)
D/dalvikvm( 2027): +++ not scanning '/system/lib/libmedia_jni.so' for
'NewTestClass_getX' (wrong CL)

As soon as the application tries to instantiate a NewTestClass object
in the onCreate method, the application terminates and I get the
following LogCat dump:

I/DEBUG ( 539): *** *** *** *** *** *** *** *** *** *** *** *** ***
*** *** ***
I/DEBUG ( 539): Build fingerprint: 'generic/sdk/generic/:1.5/
CUPCAKE/148875:eng/test-keys'
I/DEBUG ( 539): pid: 2027, tid: 2027 >>> com.example.newtest <<<
I/DEBUG ( 539): signal 7 (SIGBUS), fault addr 00000000
I/DEBUG ( 539): r0 42382b49 r1 4359d428 r2 00000000 r3 00000000
I/DEBUG ( 539): r4 be9a4540 r5 00000004 r6 804005f0 r7 41049d10
I/DEBUG ( 539): r8 be9a451c r9 41049d04 10 41049cf4 fp 00000000
I/DEBUG ( 539): ip 804005f0 sp be9a4508 lr 80400604 pc
804005e8 cpsr 80000010
I/DEBUG ( 539): #00 pc 000005e8 /data/data/
com.example.newtest/lib/libnewtest.so
I/DEBUG ( 539): #01 pc 00000600 /data/data/
com.example.newtest/lib/libnewtest.so
I/DEBUG ( 539): #02 pc 0000e3b4 /system/lib/libdvm.so
I/DEBUG ( 539): stack:
I/DEBUG ( 539): be9a44c8 000000da
I/DEBUG ( 539): be9a44cc 000001b8
I/DEBUG ( 539): be9a44d0 00003071
I/DEBUG ( 539): be9a44d4 afe0af93 /system/lib/libc.so
I/DEBUG ( 539): be9a44d8 804005f0 /data/data/
com.example.newtest/lib/libnewtest.so
I/DEBUG ( 539): be9a44dc 00000006
I/DEBUG ( 539): be9a44e0 afe3c980
I/DEBUG ( 539): be9a44e4 afe39dd0
I/DEBUG ( 539): be9a44e8 0000a000 [heap]
I/DEBUG ( 539): be9a44ec 00000088
I/DEBUG ( 539): be9a44f0 42382b49
I/DEBUG ( 539): be9a44f4 00000000
I/DEBUG ( 539): be9a44f8 0018cbe8 [heap]
I/DEBUG ( 539): be9a44fc 000e1940 [heap]
I/DEBUG ( 539): be9a4500 df002777
I/DEBUG ( 539): be9a4504 e3a070ad
I/DEBUG ( 539): #01 be9a4508 00000000
I/DEBUG ( 539): be9a450c 00000000
I/DEBUG ( 539): be9a4510 00000002
I/DEBUG ( 539): be9a4514 ad00e3b8 /system/lib/libdvm.so
I/ActivityManager( 570): Process com.example.newtest (pid 2027) has
died.
D/Zygote ( 541): Process 2027 terminated by signal (7)

I hope my explanation has been sufficiently elaborate. Has anyone any
experience on using SWIG on the Android platform and could point out
what is wrong with my approach?

Many thanks in advance,
Maarten Wijnants

Maarten Wijnants

unread,
Jul 9, 2009, 7:42:37 AM7/9/09
to android-ndk
As I did not find any solution to this strange problem, I tried
compiling the native library using the agcc build script (http://
plausible.org/andy/agcc). Surprisingly, now everything works as
expected! In other words, I am able to use my native code in Java as I
would in a C++ environment.

Unfortunately however, I still have no clue as to why compilation
using the Android NDK does not work. If anyone could shed some
insight, that would be greatly appreciated!

Sridhar M

unread,
Jul 31, 2009, 10:32:41 AM7/31/09
to andro...@googlegroups.com
Maarten,

I have used the SWIG framework on Android and it works.
From your logs it seems that JNI_OnLoad() is not implemented in your native library. Be sure to register all the native JNI methods using JNI_OnLoad() ( maybe in newtestclass_wrap.cpp )

Regards,
Sridhar

Maarten Wijnants

unread,
Aug 26, 2009, 8:01:33 AM8/26/09
to android-ndk
Hello Sridhar,

Many thanks for your reply! I am sorry I did not respond sooner, I
only just noticed someone replied on my question.

On 31 jul, 16:32, Sridhar M <sridhar....@gmail.com> wrote:
> Maarten,
>
> I have used the SWIG framework on Android and it works.
> From your logs it seems that JNI_OnLoad() is not implemented in your native
> library. Be sure to register all the native JNI methods using JNI_OnLoad() (
> maybe in newtestclass_wrap.cpp )

Indeed I did not implement the JNI_OnLoad method. I saw LogCat
printing a warning about this, but adding the method did not help me.
Maybe I did something wrong in the JNI_OnLoad implementation, I'm not
sure. Anyway, using the agcc build script, I was able to successfully
get SWIG to work, WITHOUT the JNI_OnLoad method. So I am still not
really sure whether native JNI method registering is absolutely
necessary.

> > Regards,
> Sridhar

Once more my gratitude for your reply! Maybe in the future I will
again look into NDK native library building (instead of using the agcc
build script). When so, I will definitely look into your suggestion of
registering native methods in the JNI_OnLoad method.

Greetz,
Maarten

Sridhar M

unread,
Sep 3, 2009, 8:30:30 AM9/3/09
to andro...@googlegroups.com
Hi Maarten,

You are welcome!
For me, the JNI interface started working only after adding JNI_OnLoad()
Here is a good reference of how the function is written
http://markmail.org/message/daqhat4un5xlbaze

Hope it helps.

Regards,
Sridhar
Reply all
Reply to author
Forward
0 new messages