我正在处理一个应用程序,在该应用程序中,我将在TreeView中显示应用程序的一些数据。很标准。我打算让显示器显示应用程序主要状态的数据,存储在TVar中的变量以及跨多个进程共享的变量。所以,我正在构建一个CustomView(并且几乎不能理解所有东西是如何组合在一起的),它可以看到那个TVar。
此时我完全在ghci
内进行测试。
我对treeViewGetIter
的呼叫正常。我在treeViewIfaceGetIter
中有一些打印信息可以在TVar中打印信息,一切看起来都不错。如果提供的路径有效,我会返回一个合理的迭代器,如果没有,则返回Nothing。
但是,当我将该迭代器传递给treeViewGetRow
时,应用程序将中止。没有错误消息,我刚刚回到命令行。我的ulimit
设置为无限制,但没有核心转储。
所以,这是设置代码:
data FileList rowtype = FileList (CustomStore (TVar (Map FilePath (LoadStatus Image))) rowtype)
instance GObjectClass (FileList (LoadStatus Image)) where
toGObject (FileList cm) = toGObject cm
unsafeCastGObject = FileList . unsafeCastGObject
instance TypedTreeModelClass FileList
instance TreeModelClass (FileList (LoadStatus Image))
makeStore :: TVar (Map FilePath (LoadStatus Image)) -> IO (FileList (LoadStatus Image))
makeStore tvLst =
customStoreNew
tvLst
FileList
TreeModelIface {
treeModelIfaceGetFlags = return [TreeModelListOnly]
, treeModelIfaceGetIter = \[n] ->
atomically $ do
unsafeIOToSTM $ putStrLn $ "Seeking element " ++ show n
var <- readTVar tvLst
unsafeIOToSTM $ putStrLn $ "tvar info: " ++ (show $ M.size var)
if M.null var || M.size var < n
then return Nothing
else return $ Just $ TreeIter 0 (fromIntegral n) 0 0
, treeModelIfaceGetPath = \(TreeIter _ n _ _) -> return [fromIntegral n]
, treeModelIfaceGetRow = \(TreeIter _ n _ _) ->
atomically $ do
unsafeIOToSTM $ putStrLn $ "Looking up row at " ++ show n
var <- readTVar tvLst
return (M.elems var !! fromIntegral n)
, treeModelIfaceIterNext = \a -> do
putStrLn "treeModelIFaceIterNext"
return Nothing
, treeModelIfaceIterChildren = \a -> do
putStrLn "treeModelIfaceIterChildren"
return Nothing
, treeModelIfaceIterHasChild = \a -> do
putStrLn "treeModelIfaceIterHasChild"
return False
, treeModelIfaceIterNChildren = \a -> do
putStrLn "treeModelIfaceIterNChildren"
return 0
, treeModelIfaceIterNthChild = \a b -> do
putStrLn "treeModelIfaceIterNthChild"
return Nothing
, treeModelIfaceIterParent = \a -> do
putStrLn "treeModelIfaceIterParent"
return Nothing
, treeModelIfaceRefNode = \a -> do
putStrLn "treeModelIfaceRefNode"
return ()
, treeModelIfaceUnrefNode = \a -> do
putStrLn "treeModelIfaceUnrefNode"
return ()
}
Nothing
Nothing
然后,这是一个互动。 tv初始化为三个条目,st通过makeStore tv
初始化:
*Main FileListModel Control.Concurrent.STM Control.Monad> :t tv
tv
:: TVar
(containers-0.5.0.0:Data.Map.Base.Map
FilePath (LoadStatus Alyra.Photos.Image.Image))
*Main FileListModel Control.Concurrent.STM Control.Monad> :t st
st :: FileList (LoadStatus Alyra.Photos.Image.Image)
*Main FileListModel Control.Concurrent.STM Control.Monad> atomically (Data.Map.size `liftM` readTVar tv)
3
*Main FileListModel Control.Concurrent.STM Control.Monad> Just iter <- treeModelGetIter st [0]
Seeking element 0
tvar info: 3
*Main FileListModel Control.Concurrent.STM Control.Monad> iter
TreeIter (-288664969) 0 0 0
*Main FileListModel Control.Concurrent.STM Control.Monad> v <- treeModelGetRow st iter
在最后一个命令之后,我重新使用bash而没有任何错误,也没有指示程序崩溃的原因。
我没有详尽地检查它们,但其他功能似乎都有效。
我对上面的声明做了一个额外的更改:
, treeModelIfaceGetRow = \n -> do
putStrLn $ "treeModelGetRow " ++ show n
return Loading
即使是现在,当与底层tvar没有交互时,我也会遇到同样的崩溃。
那么,我该如何诊断这种错误呢?我实际上不知道如何开始,因为它是C和Haskell之间的互动。而且,就此而言,GTK所要求的是否有任何明显的错误?
(为了记录,我在设置TreeStore之前调用了initGUI,但这部分并未包括在内)