Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running simple winforms application on Mono for ARM

I am currently trying to set up an environment in which I can create winform applications with Visual Studio 2013 that I then want to put on an ARM v7 BeagleBone Black with an attached touchscreen where they are supposed to run with Mono.

In order to do so, I took a Ubuntu 14.10 AMD64 system and created a cross-compile environment with the BeagleBone Black's toolchain and scratchbox2.

I verified that the toolchain an sb2 work correctly by compiling some native test programs with it, they do run flawlessly on the Ubuntu machine (with sb2) as well as on the BeagleBone Black.

Next, I compiled mono from source, once for the Ubuntu machine and also once for the BeagleBone Black. To do so, I mainly followed this post. In the end I had a directory with the complete mono tree whose native components had been correctly compiled for ARM. I verified that by running sb2 mono -V on the Ubuntu system as well as mono -V on the BeagleBone Black after copying the mono directory onto it. I can also run a simple .NET console application that I created with VS2013 on the BBB's mono.

Next I tried to run a simple GUI application that basically only consists of a single form and a button that pops up a messagebox. The project settings in VS were set to .NET Framework version 4.5 and "Release".

Next, I tried to run this EXE with mono on the Ubuntu system and it worked after tweaking the ./configure options, recompiling mono (--with-tls=__thread) and installing the required libraries (libgdiplus and libx11). But when I try to run the same EXE on the BBB it crashes with this exception:

Unhandled Exception:
System.ArgumentException: A null reference or invalid value was found [GDI+ status: InvalidParameter]
  at System.Drawing.GDIPlus.CheckStatus (Status status) [0x00000] in <filename unknown>:0 
  at System.Drawing.Bitmap..ctor (Int32 width, Int32 height, PixelFormat format) [0x00000] in <filename unknown>:0 
  at System.Drawing.Bitmap..ctor (System.Drawing.Image original, Int32 width, Int32 height) [0x00000] in <filename unknown>:0 
  at System.Drawing.Bitmap..ctor (System.Drawing.Image original, Size newSize) [0x00000] in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) System.Drawing.Bitmap:.ctor (System.Drawing.Image,System.Drawing.Size)
  at System.Windows.Forms.XplatUIX11.DefineCursor (System.Drawing.Bitmap bitmap, System.Drawing.Bitmap mask, Color cursor_pixel, Color mask_pixel, Int32 xHotSpot, Int32 yHotSpot) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.XplatUI.DefineCursor (System.Drawing.Bitmap bitmap, System.Drawing.Bitmap mask, Color cursor_pixel, Color mask_pixel, Int32 xHotSpot, Int32 yHotSpot) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Cursor.CreateCursor (System.IO.Stream stream) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Cursor..ctor (System.Type type, System.String resource) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Cursors.get_SizeNWSE () [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.SizeGrip..ctor (System.Windows.Forms.Control CapturedControl) [0x00000] in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) System.Windows.Forms.SizeGrip:.ctor (System.Windows.Forms.Control)
  at System.Windows.Forms.ScrollableControl.CreateScrollbars () [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.ScrollableControl..ctor () [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.ContainerControl..ctor () [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Form..ctor () [0x00000] in <filename unknown>:0 
  at guitest.Form1..ctor () [0x00000] in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) guitest.Form1:.ctor ()
  at guitest.Program.Main () [0x00000] in <filename unknown>:0 
[ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentException: A null reference or invalid value was found [GDI+ status: InvalidParameter]
  at System.Drawing.GDIPlus.CheckStatus (Status status) [0x00000] in <filename unknown>:0 
  at System.Drawing.Bitmap..ctor (Int32 width, Int32 height, PixelFormat format) [0x00000] in <filename unknown>:0 
  at System.Drawing.Bitmap..ctor (System.Drawing.Image original, Int32 width, Int32 height) [0x00000] in <filename unknown>:0 
  at System.Drawing.Bitmap..ctor (System.Drawing.Image original, Size newSize) [0x00000] in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) System.Drawing.Bitmap:.ctor (System.Drawing.Image,System.Drawing.Size)
  at System.Windows.Forms.XplatUIX11.DefineCursor (System.Drawing.Bitmap bitmap, System.Drawing.Bitmap mask, Color cursor_pixel, Color mask_pixel, Int32 xHotSpot, Int32 yHotSpot) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.XplatUI.DefineCursor (System.Drawing.Bitmap bitmap, System.Drawing.Bitmap mask, Color cursor_pixel, Color mask_pixel, Int32 xHotSpot, Int32 yHotSpot) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Cursor.CreateCursor (System.IO.Stream stream) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Cursor..ctor (System.Type type, System.String resource) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Cursors.get_SizeNWSE () [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.SizeGrip..ctor (System.Windows.Forms.Control CapturedControl) [0x00000] in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) System.Windows.Forms.SizeGrip:.ctor (System.Windows.Forms.Control)
  at System.Windows.Forms.ScrollableControl.CreateScrollbars () [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.ScrollableControl..ctor () [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.ContainerControl..ctor () [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Form..ctor () [0x00000] in <filename unknown>:0 
  at guitest.Form1..ctor () [0x00000] in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) guitest.Form1:.ctor ()
  at guitest.Program.Main () [0x00000] in <filename unknown>:0 

I wonder what the problem might be? How can I go on from here?

BTW: This is the mono version on the BBB:

Mono JIT compiler version 3.12.0 (tarball Mo 23. Feb 11:40:46 CET 2015)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
    TLS:           __thread
    SIGSEGV:       normal
    Notifications: epoll
    Architecture:  armel,vfp+fallback
    Disabled:      none
    Misc:          softdebug 
    LLVM:          supported, not enabled.
    GC:            sgen

Update: I just noticed this little mono utility called mono-test-install. When I run it on the BBB, it tells me this:

./mono-test-install 
Active Mono:
Warning: pkg-config could not find mono installed on this system
No dotnet pkgconfig found, Windows.Forms, System.Drawing and others will not work

I think that may be my problem. Does somebody know how to get things on track in this case? I assume that I somehow have to tell mono where it can find its libraries and assemblies, but I can't tell for sure... It would be great if someone could shed some light on this.

Update 2: I was able to get rid of the error shown by mono-test-install by creating the relevant environment variables for my hand-made mono version (described here). Also, I had to edit the file [mono-directory]/usr/local/bin/mcs and correct the paths to the executables. I assume you can set them automatically with PREFIX=... when you configure mono, but I didn't do that.

Now, when I run mono-test-install I get this:

Active Mono: /home/root/monotree_armv7/usr/local/bin/mono
Other Mono executables: /usr/local/bin/mono 

Your have a working System.Drawing setup
Your file system watcher is: System.IO.InotifyWatcher

So I think there should be everything in place and set up correctly now. But it still does not work. When I run my little winforms test program, I get the very same exception as given above.

After some searching I found out that there is probably a bug in mono as I am not the first one to run into this. The strange thing however is the fact that the same EXE runs flawlessly on Ubuntu with the very same mono version (just compiled for amd64 and not armv7, same configure options). So on the PC everything works fine, on arm it crashes.

Update: I filed a report with an attached sample project that produces the problems here.

like image 777
Rob Avatar asked Feb 23 '15 13:02

Rob


1 Answers

A bit of digging shows that GDI+ GdipCreateBitmapFromScan0 returns InvalidParameter when width or height is a non-positive number.

Going upper the stack trace indicates that Bitmap constructor is called from X11 driver when preferred cursor size (reported by XQueryBestCursor from libX11) differs from original cursor size (which is 32x32 pixels).

So the thought is that XQueryBestCursor() on your BeagleBone returns zero width/height for cursor. A bit of googling gets us to the thread describing a similar issue. There's even some kind of patch there.

I believe you should either recompile X11 on your BeagleBone with a patch provided, or add some checks in mono source (after calling XQueryBestCursor) so it use cursor's original width/height when X11 returns zero width/height.

UPD: HW cursor size seems to be actually reported by video driver, so you can probably just try another one, like recent xf86-video-fbdev.

like image 61
Alex Skalozub Avatar answered Sep 19 '22 14:09

Alex Skalozub