1

I've written a program in WXHaskell, and verified that it works. Long story short, I planned for the program to be usable via GUI or by command line interface. I later went on to add command line argument processing with the GetOpts library and began testing that the various arguments worked as intended.

However, once I began running the program with command line options, the program began failing: any time the program was invoked in GUI mode (i.e. running WXHaskell) the program crashed with a warning about unrecognized command line options (this warning was in the form of a WXwidgets popup window). Anytime the program was run in terminal mode, all the options were processed correctly, so my suspicion is that running WX computations causes the "ARGV" values to be passed to some WX function down the line, and of course since these args are intended for the main program body, they will be unrecognized.

I've written a small test-case that reproduces this behavior (without GetOpts).

import Graphics.UI.WX
import System.Environment (getArgs)

gui = do
  fr <- frame [text := "GUI calculation"]
  t <- staticText fr [text := "Enter a number below"]
  n <- entry fr []
  let foo = do
        v <- read <$> get n text
        set t [text := "Your number * 3 is " ++ show (v * 3 :: Int) ]
  b <- button fr [text := "Calculate", on command := foo]
  set fr [layout := column 3 [widget t, widget n, widget b] ]

terminal = do
  putStrLn "Enter a number"
  v <- read <$> getLine
  putStrLn $ "Your number * 3 is " ++ (show $ v * 3)

main = do
  a <- getArgs
  case a of
    ("terminal"):_ -> terminal
    ("gui"):_ -> start gui
    _ -> start gui

Command line args are processed, and the computation (simply multiplying a user-specified Int by 3) is run either on the terminal or through a gui.

If the user specifies "terminal", the program completes without problem. If the user specifies no args the computation is run in gui mode by default, and also completes normally.

If the user specifies the "gui" argument, the program crashes with an error (in a popup window): "Unexpected parameter 'gui'".

If anyone has any idea why my args are apparently being passed on to subsequent operations, or better yet, how to stop this from happening, I'd be very happy!

Ben
  • 205
  • 2
  • 5
  • It looks like the function in [Graphics.UI.WXCore.Events](http://hackage.haskell.org/package/wxcore-0.92.2.0/docs/src/Graphics-UI-WXCore-Events.html) 'appOnInit', which is called indirectly by WX's 'start', passes the argv onto the C code initializing the WX process. I've rewritten my own 'start', 'run' and 'appOnInit' to circumvent this, as per [here](http://hackage.haskell.org/package/wxcore-0.92.2.0/docs/src/Graphics-UI-WXCore-Events.html), to control what is being passed to WX, but it still doesn't work (even passing [] to this function still results in WX incorrectly receiving my argv) – Ben Jul 13 '16 at 07:00
  • My intuition now tells me that what would be needed would be to somehow nullify the argv array _after_ my Haskell program has extracted what data it needs from the args, but _before_ any WX functions are called, though I have no idea how to do this. I assume an external C function that had access to argv[] would be able to set all of the *argv pointers to NULL, tricking WX into thinking there were no command line arguments passed, but this is a bit beyond the scope of my knowledge. – Ben Jul 13 '16 at 07:06

1 Answers1

4

I have experienced the same problem. My workaround was to use withArgs to start the GUI without any command line arguments like so:

main = do
  a <- getArgs
  case a of
    ("terminal"):_ -> terminal
    ("gui"):_ -> withArgs [] (start gui)
    _ -> withArgs [] (start gui)
phischu
  • 440
  • 2
  • 6
  • Thank, I tried this but I'm still getting a popup error window complaining about the unrecognized 'gui' parameter in the second case. As mentioned above, I've gone as far as rewriting the WX libraries' 'start', 'gui', and 'appOnInit' to ensure that no args are passed to wxcAppInitializeC downstream in the WX initialization code, but still get this error. My guess is that whatever code is being run downstream still has access to the original argc/argv memory locations and is using them in spite of not being passed any args directly by the Haskell code. – Ben Jul 13 '16 at 23:48
  • Could you tell me, @phischu , which version of the wx Haskell libs you were using when you had this problem? I'm using 0.92.2.0 currently. – Ben Jul 14 '16 at 00:11
  • I am using wx-0.92.1.0. – phischu Jul 14 '16 at 11:02