Hack iOS for fun and profit

606 views
Skip to first unread message

Michael Bayne

unread,
Jan 17, 2012, 4:10:08 PM1/17/12
to pl...@googlegroups.com
As promised, I've tidied things up and made the iOS backend somewhat
consumable by people that aren't me.

There are a few moving parts to the new iOS backend, which I'll summarize:

1. The playn.ios package itself, which is currently only in OOO's
PlayN repository. You can check that out here:

git://github.com/threerings/playn.git

2. The Java "bindings" to the CLR and MonoTouch C# libraries. I put
bindings in quotes because they're not bindings per se, they are Java
class files that allow one to write Java code that references the C#
assemblies, and when everything is later run through IKVM, those
references are turned into direct references to the C# assembles, so
the Java "bindings" disappear. These are published to the ForPlay
legacy Maven repository, so you don't need to do anything to obtain
them. The standard Maven build process will download them.

3. The Silverlight-profile-compatible build of IKVM. This can be
obtained here: http://dl.dropbox.com/u/404021/ikvm-monotouch.zip

4. Mono and MonoTouch (http://xamarin.com/monotouch). I'm using a Mac,
though in theory all of this will work on Linux or Windows, but I'm
making no promises to provide technical support on that front. If you
want to try this stuff out currently, you may need to expend some
effort. You also need to install MonoDevelop
(http://monodevelop.com/).

Now on to the actual building and testing:

Having cloned the OOO PlayN, you'll need to run "mvn install" therein.

Then "git pull" your playn-samples repository and you'll see that the
iOS bootstrap has been added to the playn-samples/hello project (in
hello/ios).

In playn/samples/hello run "mvn package".

Then "cd ios" and run build-dll.sh (you will need to edit the script
and change IKVM_HOME to wherever you unpacked ikvm-monotouch.zip).
This will run IKVM on the PlayN and hello-core jar files to generate
hello-core.dll.

Now edit the hello.csproj MonoDevelop project file and update the path
to ikvm-monotouch so that the project can find the
IKVM.OpenJDK.Core.dll.

Finally, open the hello.sln file in MonoDevelop. Then press the little
build button in the tool bar, followed by the debug button, which
should launch your simulator, running the Hello sample. This will just
show you the rainbow background, since that's what the sample does by
default. Touch input isn't working yet, so you can't add peas, but you
can modify HelloGame.java thusly if you want to see something move:

diff --git i/hello/core/src/main/java/playn/sample/hello/core/HelloGame.java
w/hello/core/src/main/java/playn/sample/hello/core/Hell
index d2155bc5cf..bdc01a1343 100644
--- i/hello/core/src/main/java/playn/sample/hello/core/HelloGame.java
+++ w/hello/core/src/main/java/playn/sample/hello/core/HelloGame.java
@@ -52,6 +52,9 @@ public class HelloGame implements Game {
peas.add(pea);
}
});
+
+ Pea pea = new Pea(peaLayer, graphics().screenWidth()/2,
graphics().screenHeight()/2);
+ peas.add(pea);
}

@Override

That's about the size of it. I'll be working on fleshing out the iOS
backend, though I'm already sidetracked because IKVM doesn't fully
support C# delegates that take ref parameters. Damn C# for adding all
this useful stuff whilst Java sat on its committee-laden ass for the
last half-decade.

-- m...@samskivert.com

Michael Bayne

unread,
Jan 17, 2012, 4:14:10 PM1/17/12
to pl...@googlegroups.com
On Tue, Jan 17, 2012 at 1:10 PM, Michael Bayne <m...@samskivert.com> wrote:
> I'm using a Mac,
> though in theory all of this will work on Linux or Windows

Oh duh. MonoTouch certainly isn't going to work on Linux or Windows
because you can't run the iPhone simulator. So I guess that simplifies
things. You need to use a Mac!

-- m...@samskivert.com

Michael Bayne

unread,
Jan 17, 2012, 5:41:30 PM1/17/12
to pl...@googlegroups.com
On Tue, Jan 17, 2012 at 1:10 PM, Michael Bayne <m...@samskivert.com> wrote:
> I'll be working on fleshing out the iOS
> backend, though I'm already sidetracked because IKVM doesn't fully
> support C# delegates that take ref parameters.

It turned out not to be that difficult to remove said limitation from
IKVM. Fortunately, the change only impacted the binding generator, so
there's no need to update ikvm-monotouch.zip. I did update the
monotouch.jar in the Maven repo, but since that's a SNAPSHOT artifact,
it should automatically be downloaded by anyone speedy enough to
already be playing with this stuff.

With that fixed, I was able to implement IOSPointer and IOSTouch, so
now you can click on the Hello demo and place rotating peas on the
screen. No longer is it necessary to visualize whirled peas, you can
see them for yourself.

-- m...@samskivert.com

Christopher Östlund

unread,
Jan 18, 2012, 4:18:05 AM1/18/12
to pl...@googlegroups.com
Awesome stuff!

Evans

unread,
Mar 25, 2012, 11:15:08 AM3/25/12
to pl...@googlegroups.com
>>3. The Silverlight-profile-compatible build of IKVM. This can be
>>obtained here: http://dl.dropbox.com/u/​404021/ikvm-monotouch.zip 

Is there a separate open source project for this, or is this something you built on your own?

Michael Bayne

unread,
Mar 25, 2012, 1:46:37 PM3/25/12
to pl...@googlegroups.com
On Sun, Mar 25, 2012 at 8:15 AM, Evans <ev...@nvolvestudios.com> wrote:
> Is there a separate open source project for this, or is this something you
> built on your own?

It's something I built on my own:

https://github.com/samskivert/ikvm-monotouch

-- m...@samskivert.com

Evans Thomas

unread,
Mar 25, 2012, 4:02:18 PM3/25/12
to pl...@googlegroups.com
Thanks! I was looking for this. I was planning to experiment with adding a backend for Windows Phone. I wasn't able to proceed since IVKM did not support the Silverlight profile. I'll give it a try now.

Evans

Evans Thomas

unread,
Mar 25, 2012, 11:12:37 PM3/25/12
to pl...@googlegroups.com
I keep getting the following error even though I have verified the correct path locations. I even tried with multiple versions of the Mono libraries.

I used the following command - 

SET MONO_PATH=C:\Program Files\Mono-2.10.8\lib\mono\4.0
ikvmc -nostdlib -debug -target:library D:\Test.class -out:Test.dll -lib:"C:\Program Files\Mono-2.10.8\lib\mono\4.0" -r:"%MONO_PATH%\mscorlib.dll"-r:"%MONO_PATH%\System.dll" -r:"%MONO_PATH%\System.Core.dll" -r:"%MONO_PATH%\System.Data.dll"

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or ass
embly 'System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
' or one of its dependencies. The system cannot find the file specified.
File name: 'System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea
7798e'
   at IkvmcCompiler.Main(String[] args)

What am I missing here?

Thanks
Evans

On Sun, Mar 25, 2012 at 11:16 PM, Michael Bayne <m...@samskivert.com> wrote:

Michael Bayne

unread,
Mar 26, 2012, 11:57:19 AM3/26/12
to pl...@googlegroups.com
On Sun, Mar 25, 2012 at 8:12 PM, Evans Thomas <ev...@nvolvestudios.com> wrote:
> What am I missing here?

I don't know. I hacked my NAnt installation to point to the MonoTouch
DLLs and had to do a lot of fiddling to get everything to reference
the correct version of the system DLLs.

If you're building with NAnt, I don't think MONO_PATH is used for
anything. NAnt sets up the paths to the system DLLs based on the -t
argument. NAnt.exe.config contains the settings for all of the
possible -t arguments. I modified the NAnt installed by Mono to point
the moonglight-2.0 framework at the MonoTouch DLLs.

I don't know what the right DLLs are for Windows phone, but you'll
need to configure NAnt to use them.

-- m...@samskivert.com

Evans Thomas

unread,
Mar 26, 2012, 2:53:22 PM3/26/12
to pl...@googlegroups.com
  No, I'm not using NAnt. It's just a simple batch file.   It directly invokes ikvmc.

Michael Bayne

unread,
Mar 27, 2012, 10:59:04 AM3/27/12
to pl...@googlegroups.com
On Mon, Mar 26, 2012 at 11:53 AM, Evans Thomas <ev...@nvolvestudios.com> wrote:
>   No, I'm not using NAnt. It's just a simple batch file.   It directly
> invokes ikvmc.

Are you running ikvmc from my ikvm-monotouch.zip? You won't be able to
just use that out of the box, because it is built against the 2.0.5.0
versions of the CLR core DLLs that ship with MonoTouch.

If you want to use my modified IKVM for Windows Phone, you'll need to
rebuild my modified IKVM against the Windows Phone CLR core DLLs.

-- m...@samskivert.com

Evans Thomas

unread,
Mar 27, 2012, 12:45:08 PM3/27/12
to pl...@googlegroups.com
Oh alright. I will try that, then. Your comments in the readme kinda scared me away from building it :)

Michael Bayne

unread,
Mar 27, 2012, 12:50:35 PM3/27/12
to pl...@googlegroups.com
On Tue, Mar 27, 2012 at 9:45 AM, Evans Thomas <ev...@nvolvestudios.com> wrote:
> Your comments in the readme kinda scared me away from building it :)

Yeah, unfortunately I don't think there's anyway to avoid diving into
the deep end.

-- m...@samskivert.com

kshush...@gmail.com

unread,
Mar 28, 2012, 11:41:16 AM3/28/12
to pl...@googlegroups.com
hi, thanks for the great work! 

I managed to get through the manual with success :) and now i would like to port my "game" (which is based on PlayN) to iOS.

Is there is a way to generate the following files for my project: Info.plist, Main.cs, mygame.csproj,  mygame.sln ...?
or should i create them manually? 

Michael Bayne

unread,
Mar 28, 2012, 12:33:19 PM3/28/12
to pl...@googlegroups.com
On Wed, Mar 28, 2012 at 8:41 AM, <kshush...@gmail.com> wrote:
> Is there is a way to generate the following files for my
> project: Info.plist, Main.cs, mygame.csproj,  mygame.sln ...?
> or should i create them manually?

Currently they have to be created manually.

-- m...@samskivert.com

Simen S.

unread,
Apr 22, 2012, 8:56:13 AM4/22/12
to pl...@googlegroups.com
Hi,

I have been tinkering a bit to see if I can get our game running on ios. So far everything has worked surprisingly well, I got everything compiling, but I get errors at runtime in the simulator. It seems to be due to our use of Guice, and its annotations, especially @Inject on constructors. Do you have any experience with this? I assume they are lost in the void at some stage?  ("Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private." ). Not sure if there is any good solution here, or if I should take the painful route of manually wiring up everything to see if I get further. 

Great work on it by the way! Between your posts here and looking at the samples it was surprisingly easy to get running. 

/Simen

Darrin Thompson

unread,
Apr 22, 2012, 9:03:03 AM4/22/12
to pl...@googlegroups.com
On Sun, Apr 22, 2012 at 8:56 AM, Simen S. <sime...@gmail.com> wrote:
> I have been tinkering a bit to see if I can get our game running on ios. So
> far everything has worked surprisingly well, I got everything compiling, but
> I get errors at runtime in the simulator. It seems to be due to our use of
> Guice, and its annotations, especially @Inject on constructors. Do you have
> any experience with this? I assume they are lost in the void at some stage?
>  ("Classes must have either one (and only one) constructor annotated with
> @Inject or a zero-argument constructor that is not private." ). Not sure if
> there is any good solution here, or if I should take the painful route of
> manually wiring up everything to see if I get further.
>

What platform was working before?

--
Darrin

Michael Bayne

unread,
Apr 22, 2012, 11:29:26 AM4/22/12
to pl...@googlegroups.com
On Sun, Apr 22, 2012 at 5:56 AM, Simen S. <sime...@gmail.com> wrote:
> It seems to be due to our use of Guice, and its annotations, especially
> @Inject on constructors. Do you have any experience with this?

In theory reflection should work in both the iOS simulator and on the
device. What errors are you getting?

-- m...@samskivert.com

Michael Bayne

unread,
Apr 22, 2012, 11:44:30 AM4/22/12
to pl...@googlegroups.com
On Sun, Apr 22, 2012 at 5:56 AM, Simen S. <sime...@gmail.com> wrote:
> It seems to be due to our use of Guice, and its annotations, especially
> @Inject on constructors.

Oh, I bet I know what the problem is. I didn't have reflected
constructors working in IKVM until fairly recently. So you should try
downloading the lastest ikvm-monotouch.zip from here and see if it
works:

http://dl.dropbox.com/u/404021/ikvm-monotouch.zip

-- m...@samskivert.com

Simen S.

unread,
Apr 23, 2012, 3:55:49 PM4/23/12
to pl...@googlegroups.com
Hi Michael,

I tried both the dropbox version, and also tried cloning your github repo and building, none of them worked, still get the same errors. 

I have uploaded a stripped out project that recreates the issues here: http://dl.dropbox.com/u/6738607/GuiceTest.zip
What I get is: 
"Unhandled Exception: com.google.inject.CreationException: Guice creation errors:

1) Could not find a suitable constructor in ClassThatInjects. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
  at ClassThatInjects.class(Unknown Source)
  at GuiceModule.configure(GuiceModule.java:12)

1 error
[ERROR] FATAL UNHANDLED EXCEPTION: com.google.inject.CreationException: Guice creation errors:

1) Could not find a suitable constructor in ClassThatInjects. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
  at ClassThatInjects.class(Unknown Source)
  at GuiceModule.configure(GuiceModule.java:12)

1 error"

I don't have eclipse on my computer, so I provided a IntelliJ project structure instead, though you don't really need to touch that unless you want to run and see what happens on the java platform. Should just be for you to run the rebuild-dll.sh script in ios directory, and edit the path in GuiceTest.csproj. 

Hopefully this provides a little help! Might just be something as simple as me forgetting a crucial step or missing an important dll file.

/Simen

Michael Bayne

unread,
Apr 23, 2012, 5:45:08 PM4/23/12
to pl...@googlegroups.com
On Mon, Apr 23, 2012 at 12:55 PM, Simen S. <sime...@gmail.com> wrote:
> "Unhandled Exception: com.google.inject.CreationException: Guice creation
> errors:
>
> 1) Could not find a suitable constructor in ClassThatInjects. Classes must
> have either one (and only one) constructor annotated with @Inject or a
> zero-argument constructor that is not private.
>   at ClassThatInjects.class(Unknown Source)
>   at GuiceModule.configure(GuiceModule.java:12)
>
> 1 error
> [ERROR] FATAL UNHANDLED EXCEPTION: com.google.inject.CreationException:
> Guice creation errors:
>
> 1) Could not find a suitable constructor in ClassThatInjects. Classes must
> have either one (and only one) constructor annotated with @Inject or a
> zero-argument constructor that is not private.
>   at ClassThatInjects.class(Unknown Source)
>   at GuiceModule.configure(GuiceModule.java:12)
>
> 1 error"

I looked into this a little, but it's pushing the deep magic that
makes the iOS backend work beyond its limits. It's frankly a small
miracle that enough of Java is supported that this could even work at
all, and I'm by no means certain that you wouldn't run into another
major roadblock once the time came to compile your app for the device
using the AOT compiler.

In theory all of Java annotations and reflection are supported by IKVM
and turned into CLR annotations and reflection, which are in theory
supported in both the desktop CLR (which runs the simulator) and on
the device (which uses the AOT compiler to generate ARM assembly from
the CLR bytecodes). However, that's already a lot of theory. Combine
that with the fact that Guice is pushing Java's reflection
capabilities to the limit and doing lots of crazy stuff (c.f. your
having to avoid using the AOP bytecode rewriting version of Guice).

I tried to find out whether the @Inject annotation is making it
through into the CLR bytecodes, but the DLL generated by IKVM causes
monodis (the javap equivalent on Mono) to segfault. I don't have any
other easy way to inspect the CLR bytecodes, and I certainly don't
have time to debug monodis. It's also possible that reflection is
failing to find the constructor in question, I think that enumeration
of constructors should work fine but maybe something is going wrong
there.

I've given you the moon (silverlight -> moonlight -> moon, ha ha...),
I'm afraid that if you want the asteroid belt as well, you're going to
have to put on your spacesuit and go get it yourself.

If you want to dig into things, I'd suggest making a test app that
uses reflection directly to enumerate the constructors of
ClassThatInjects, and make sure they show up. Then manually check to
see if the @Inject annotation is showing up. If one of those things is
failing, then you at least know where to look if you choose to go
spelunking in the ikvm-monotouch code.

-- m...@samskivert.com

Darrin Thompson

unread,
Apr 23, 2012, 6:37:10 PM4/23/12
to pl...@googlegroups.com
On Mon, Apr 23, 2012 at 5:45 PM, Michael Bayne <m...@samskivert.com> wrote:
> In theory all of Java annotations and reflection are supported by IKVM
> and turned into CLR annotations and reflection, which are in theory
> supported in both the desktop CLR (which runs the simulator) and on
> the device (which uses the AOT compiler to generate ARM assembly from
> the CLR bytecodes). However, that's already a lot of theory. Combine
> that with the fact that Guice is pushing Java's reflection
> capabilities to the limit and doing lots of crazy stuff (c.f. your
> having to avoid using the AOP bytecode rewriting version of Guice).
>

Probably this is new to no one here but Gin is supposed to provide a
subset of Guice features but in a way that works with GWT. Basically
all the injection stuff is figured out at compile time. Is Gin's dark
magic likely to be compatible with the rest of the PlayN backends?

Michael Bayne

unread,
Apr 23, 2012, 6:42:15 PM4/23/12
to pl...@googlegroups.com
On Mon, Apr 23, 2012 at 3:37 PM, Darrin Thompson <darr...@gmail.com> wrote:
> Probably this is new to no one here but Gin is supposed to provide a
> subset of Guice features but in a way that works with GWT. Basically
> all the injection stuff is figured out at compile time. Is Gin's dark
> magic likely to be compatible with the rest of the PlayN backends?

I haven't looked at Gin, but I suspect they'll be wildly incompatible.
I expect that Gin will make use of GWT's generator infrastructure to
evaluate all of the metadata bits at compile time and hardwire the
dependencies then.

A working Guice on iOS would ostensibly use the same mechanisms that
Java's Guice does (reflection), but it's currently suffering from
"translate joke into Russian, then into French, then back into
English" difficulties.

-- m...@samskivert.com

Christopher

unread,
Aug 16, 2012, 7:21:40 AM8/16/12
to pl...@googlegroups.com
Hello,

I'm about to dig into this too, the issues with Guice. I just wanted check if there has been any more debugging or new versions of the different parts that might have fixed this. I'm about to set up the simple test project to see for myself. Something that I guess is positive is that we use a small subset of the features that Guice offer, to be in line with what Gin supports. So no AOP and such.

If it doesn't work I see three paths forward that I will investigate (in order of preference):

1. Dig into why constructor annotations doesn't work (if I get this to work, it might lead to further issues as mentioned)
2. Generate code for the dependency graph wiring based on something similar to Gin
3. Manually write and maintain code for wiring the app (I'm sure this would slowly consume my will to live)

Any comments, thoughts or ideas would be great.

-Christopher

Michael Bayne

unread,
Aug 16, 2012, 11:56:15 AM8/16/12
to pl...@googlegroups.com
On Thu, Aug 16, 2012 at 4:21 AM, Christopher
<christophe...@gmail.com> wrote:
> I just wanted check if there has been any more debugging or new versions of
> the different parts that might have fixed this.

One thing that may have been fixed since you last tried this is
reflective constructor invocation. So you'll want to download the most
recent build of ikvm-monotouch or build it yourself from source:

https://dl.dropbox.com/u/404021/ikvm-monotouch.zip
https://github.com/samskivert/ikvm-monotouch

-- m...@samskivert.com

Christopher Östlund

unread,
Aug 17, 2012, 5:36:06 AM8/17/12
to pl...@googlegroups.com
Thanks for the update! I still can't the constructor annotations to work. But I think I get further when using a toConstructor binding (manually selecting a constructor without reflection(?)), or using a zero arg constructor without any dependencies. In both those cases I get the same error:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object
  at IKVM.Internal.ReflectUtil.IsVector (System.Type type) [0x00000] in /Users/mdb/projects/ikvm-monotouch/runtime/ReflectUtil.cs:114 
  at IKVM.NativeCode.ikvm.runtime.Util.getFriendlyClassFromType (System.Type type) [0x00013] in /Users/mdb/projects/ikvm-monotouch/runtime/common.cs:500 
  at ikvm.runtime.Util.getFriendlyClassFromType (System.Type t) [0x00000] in <filename unknown>:0 
  at java.lang.Class.op_Implicit (System.Type type) [0x00000] in <filename unknown>:0 
  at playn.sample.hello.ios.AppDelegate.FinishedLaunching (MonoTouch.UIKit.UIApplication app, MonoTouch.Foundation.NSDictionary options) [0x0001b] in /Users/christopher/Downloads/GuiceTest/ios/Main.cs:18 
  at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
  at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00042] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:29 
  at playn.sample.hello.ios.Application.Main (System.String[] args) [0x00000] in /Users/christopher/Downloads/GuiceTest/ios/Main.cs:32 
[ERROR] FATAL UNHANDLED EXCEPTION: System.NullReferenceException: Object reference not set to an instance of an object
  at IKVM.Internal.ReflectUtil.IsVector (System.Type type) [0x00000] in /Users/mdb/projects/ikvm-monotouch/runtime/ReflectUtil.cs:114 
  at IKVM.NativeCode.ikvm.runtime.Util.getFriendlyClassFromType (System.Type type) [0x00013] in /Users/mdb/projects/ikvm-monotouch/runtime/common.cs:500 
  at ikvm.runtime.Util.getFriendlyClassFromType (System.Type t) [0x00000] in <filename unknown>:0 
  at java.lang.Class.op_Implicit (System.Type type) [0x00000] in <filename unknown>:0 
  at playn.sample.hello.ios.AppDelegate.FinishedLaunching (MonoTouch.UIKit.UIApplication app, MonoTouch.Foundation.NSDictionary options) [0x0001b] in /Users/christopher/Downloads/GuiceTest/ios/Main.cs:18 
  at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
  at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00042] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:29 
  at playn.sample.hello.ios.Application.Main (System.String[] args) [0x00000] in /Users/christopher/Downloads/GuiceTest/ios/Main.cs:32 

I am going to look into ReflectUtil.cs right now to see if I can see why that happens. Any thoughts are welcome :)

-Christopher


--




Christopher Östlund

unread,
Aug 21, 2012, 8:16:42 AM8/21/12
to pl...@googlegroups.com
I've been building ikvm-monotouch from source with some addition of random uneducated debug prints. I've been trying to figure out from which part of Guice the call to  "at java.lang.Class.op_Implicit (System.Type type) [0x00000] in <filename unknown>:0"  is made. The type variable is null there already. My guess is that some feature of Guice is looking up a class in some way that's not fully working. Any pointers on how to debug that? Could the ikvm guys have any insight on this?

I've updated the test project to not rely on constructor annotations. https://www.dropbox.com/s/d5u1mi3n6zo58im/guicetest.zip

As this is not my field of expertise (I wonder what is!) I'm leaning towards making our own mini Gin for the iOS platform instead.

-Christopher

pauli.sa...@rovio.com

unread,
Jan 24, 2013, 9:34:35 AM1/24/13
to pl...@googlegroups.com
Hi

I was wondering if you ever got the Playn+Guice+iOS combination working? I'm about to experiment with this in the near future and this seems to be the only thing that might prevent me from creating an iOS game. I depend too much on Guice. So much in fact that I don't know how to program without it anymore.

Reply all
Reply to author
Forward
Message has been deleted
0 new messages