Android NDK shared libraries

This morning, I got stumped by the Java/NDK integration. I was trying to add another shared library (Lua) to a project, and kept getting these dynamic linker error messages:

I/ActivityManager( 1386): Start proc org.libsdl.app for activity org.libsdl.app/.SDLActivity: pid=25826 uid=10087 gids={1015}
W/dalvikvm(25826): Exception Ljava/lang/UnsatisfiedLinkError; thrown during Lorg/libsdl/app/SDLActivity;.<clinit>
W/dalvikvm(25826): Class init failed in newInstance call (Lorg/libsdl/app/SDLActivity;)
W/dalvikvm(25826): threadid=1: thread exiting with uncaught exception (group=0x40020ac0)
E/AndroidRuntime(25826): FATAL EXCEPTION: main
E/AndroidRuntime(25826): java.lang.ExceptionInInitializerError
E/AndroidRuntime(25826):        at java.lang.Class.newInstanceImpl(Native Method)
E/AndroidRuntime(25826):        at java.lang.Class.newInstance(Class.java:1429)
E/AndroidRuntime(25826):        at android.app.Instrumentation.newActivity(Instrumentation.java:1021)
E/AndroidRuntime(25826):        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2577)
E/AndroidRuntime(25826):        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
E/AndroidRuntime(25826):        at android.app.ActivityThread.access$2300(ActivityThread.java:125)
E/AndroidRuntime(25826):        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
E/AndroidRuntime(25826):        at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(25826):        at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime(25826):        at android.app.ActivityThread.main(ActivityThread.java:4627)
E/AndroidRuntime(25826):        at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(25826):        at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime(25826):        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
E/AndroidRuntime(25826):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
E/AndroidRuntime(25826):        at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime(25826): Caused by: java.lang.UnsatisfiedLinkError: Library main not found
E/AndroidRuntime(25826):        at java.lang.Runtime.loadLibrary(Runtime.java:461)
E/AndroidRuntime(25826):        at java.lang.System.loadLibrary(System.java:557)
E/AndroidRuntime(25826):        at org.libsdl.app.SDLActivity.<clinit>(SDLActivity.java:53)
E/AndroidRuntime(25826):        … 15 more
W/ActivityManager( 1386):   Force finishing activity org.libsdl.app/.SDLActivity

What it was was that my Activity (which is a small java stub) needed to call System.loadLibrary(“Lua”); to load that new library. How is that related to the error message? I have no idea.

Sigh. Sometimes missing a single line will cost you half a day.

SDL on Android

Here’s a quick summary of how I got SDL to work on Android. First off, this is my setup:

  • Android NDK r6
  • Android SDK r12
  • SDL-2.0.0-6284

The first piece of bad news is that Android support is only in the upcoming SDL 2.0, not in the current stable 1.2. Although I’m sure it could be backported, SDL2 is pretty similar, so I decided to upgrade. The README.android file does a pretty good job of explaining the steps, but there were a few kinks:

  1. in jni/src/Android.mk, the line LOCAL_SHARED_LIBRARIES := SDL is wrong. That needs to be SDL2
  2. Java didn’t like that all the classes in src/org/libsdl/app/SDLActivity.java are in one file. I had to make separate SDLMain.java and SDLSurface.java files.
  3. In the onTouch method, I get a compile error (cannot find symbol) for event.getActionIndex() and event.getActionMasked(), so I commented out some of that code and haven’t used touch events yet. I still need to crack this nut.
  4. Because my SDK is installed in C:Googleandroid-sdk-windows, I had to edit local.properties to say sdk.dir=/Google/android-sdk-windows

Now I have one of the SDL test app running on my phone, drawing rectangles. Time to see if I can do something useful with that!

DirectX SDK vs. Windows SDK

Enno: this article! http://msdn.microsoft.com/en-us/library/windows/desktop/ee663275(v=vs.85).aspx
Enno: “Starting with Windows Developer Preview, the DirectX SDK is included as part of the Windows SDK.”
Kael: yep
Kael: DERP
Kael: that also means they don’t push out frequent dx sdk updates anymore
Kael: you get to wait for the next windows sdk update
Enno: what is “Windows Developer Preview”?
Enno: has that happened?
Kael: that’s part of why some people were claiming that directx is dying a slow death
Enno: is the 2010 update the most recent?
Kael: windows developer preview is windows 8 that you install in a vm
Kael: and visual studio that you have to run inside the windows 8 vm
Kael: it’s retarded because the visual studio division is currently buried deep inside their own ass
Enno: okay, so for me on Win7, with VS 2010, this should not apply?
Kael: yeah, for you you get to use old sdks
Kael: they aren’t releasing new sdks for you
Kael: not yet, anyway.
Kael: i think once windows 8 is out they may release a new one that will work on windows 7
Enno: that is totally confusing, because this link is the topmost article on http://msdn.microsoft.com/en-us/directx/
Kael: D3DX is not considered the canonical API for using Direct3D in Windows Developer Preview and therefore does not ship in the corresponding Windows SDK. You are recommended to investigate alternate solutions for working with the Direct3D API. For legacy projects such as the Windows 7 (and earlier) DirectX SDK samples, the following steps are necessary to build applications with D3DX using the DirectX SDK:
Kael: windows 7 is ‘legacy’
Enno: and i thought “oh, that explains why the last SDK is from 2010 – it’s no longer the way to do things”
Kael: no, it’s just from 2010 because microsoft is totally fucking up directx
Kael: someone wrote a good blog post explaining this stuff, sec
Enno: I am trying to compile some shit, and I want to install the right SDK, and fucking msdn is leading me astray
Kael: http://ventspace.wordpress.com/2011/11/28/directx-and-xna-status-report/
Enno: plus, the Windows SDK for Win7 will not install if you have the VC++ Redist files installed already. which _really_ ruined my day
Enno: because error messages are for pussies.
Enno: 🙁
Enno: okay, marty. we’re going back to the future. set the flux compensator for 2010

Windows SDK installation woes. Update: Solved, sort of.

My computer doesn’t have a dxsdkver.h file. That should be in the DirectX SDK. Except that no longer exists, and is now part of the Windows SDK (latest version: 7.1). That should have been installed with Visual Studio, but somehow my computer is very special, once again.

So today I tried installing the Windows SDK, and I get this feeling of deja vu:

A problem occurred while installing selected Windows SDK components.

Setup could not find the file WinSDKhelpWinSDKHelp_x86.msi at any of the specified source locations http://download.microsoft.com/download/A/6/A/A6AC035D-DA3F-4F0C-ADA4-37C8E5D34E3D/setup

I cannot install the Windows SDK, and I have been here before! In fact, my Firefox history still remembers half the links that a cursory Google search lists as visited. I hope it doesn’t mean I have to reinstall Visual Studio.

Update 1: I downloaded the Windows SDK 7.1 ISO, ran the setup from that, and now I get this message:

Installation of the “Microsoft Windows SDK for Windows 7” product has reported the following error: Please refer to SamplesSetupHTMLConfigDetails.htm document for further information.

What the Hell? That tells me nothing. Google points me to this page of regedit fuckery, which seems like something I tried last time I was here, but will be the next thing I try.

Update 2: Well, that didn’t work either. The next advice I followed was from this forum post, which suggested to uncheck the compilers (since I believe I have the SP1 compiler installed), but again, no dice. Time to try installing one component at a time, and fine-combing the log file each time one fails.

Update 3: Never mind what I just wrote. It turns out even when I deselect every single option in the installer, the installation still fails.

=== Logging started: 2/19/2012  18:05:16 ===

Action start 18:05:16: INSTALL.

Action start 18:05:16: DDSE_CA_Uninstall_InstallExecuteSequenceStarts_x86.

02/19/12 18:05:16 DDSet_Status: LANGID: 1033

02/19/12 18:05:16 DDSet_Entry: ImmediateDispatch: DDSE_CA_Uninstall_InstallExecuteSequenceStarts entry

02/19/12 18:05:16 DDSet_Error: Patch Hooks: Missing required property ‘ProductFamily’: Setup cannot continue.

02/19/12 18:05:16 DDSet_Warning: Setup failed while calling ‘getDLLName’. System error: Cannot create a file when that file already exists.

Every log file has entries like this, which seems to indicate that something that’s already installed is causing an issue with this installer. WTF.

Update 4: Progress!

Further on, the log file said that

vcredist_x86.exe installation failed with return code 5100

On a whim, I uninstalled the Visual C++ 2010 x86 Redistributable from the control panel, then tried the “empty” installation again, and Heureka! It worked.

Maybe now I can install the full product?

Installation of the “Microsoft Windows SDK for Windows 7 Compilers for x86” product has reported the following error: Fatal error during installation.

Let me just uninstall “Microsoft Visual C++ Compilers 2010 SP1 Standard – x86. I’m pretty sure I can install them again later. and oh wonder, the installation finishes!

Still doesn’t include dxsdkver.h, though. I think my initial research must have been faulty.

The problem with tolua++ and DLLs (solved!)

Today I was going to make a tiny DLL that binds some C code with tolua++, and I ran into this error message:

lua: error loading module ‘foo’ from file ‘daisydebugfoo.dll’:

        The specified procedure could not be found.

That looks like my DLL isn’t exporting the luaopen_foo function correctly. That is the function lua calls to initialize the package it just opened, and tolua++ was not declaring it properly:

TOLUA_API int luaopen_foo (lua_State* tolua_S) {
  return tolua_foo_open(tolua_S);
};

TOLUA_APIis defined toextern, which doesn’t mean that it will be exported by the DLL, because on windows, the magic incantation for that is__declspec(dllexport). The tolua++ header has no special treatment for Windows, so I’m guessing that problem has just never come up for them.

Once the problem is understood, the solution is easy: I added another function to dllmain.cpp that has the correct export declaration and calls the generated one.

extern "C" {
  int tolua_bar_open(lua_State*);
  int __declspec(dllexport) luaopen_foo (lua_State* L) {
    return tolua_bar_open(L);
  };
}

There’s one caveat, because tolua++ has already created a function named luaopen_foo, so I had to tell it to name things differently, for which there is a command-line argument:

tolua++ -n bar foo.pkg > foo.c

Domain expired :-(

Gmail has been sorting dyndns.org emails into my spam folder, so I missed the expiration notice for enno.homeunix.net – a domain I’ve used for years to point to my blog du jour.

Additionally, ennos.homes.pages.de, which points to the defunct address, no longer has an interface for administration. I’ve used that URL about as much as the other, and for longer, so pretty much every URL pointing to my blog anywhere on the internet is now wrong, with no way for me to fix them.

That is a pretty terrible state of affairs. Time to buy some domain names.