2016-08-24 9 views
6

HaskellアプリケーションからBasler USB3カメラとインターフェイスしようとしていますが、このカメラにはC++ライブラリが付属しているので、かなり簡単です。 - libbasler.so私は共有ライブラリを構築するために、このソースコードを使用しましたHaskellからFFIブロック経由で共有ライブラリを呼び出すとき、Cプログラムからリンクされているときには共有されません

extern "C" { 
    void basler_init() { 
    PylonAutoInitTerm pylon; 
    CInstantCamera camera(CTlFactory::GetInstance().CreateFirstDevice()); 
    camera.RegisterConfiguration((CConfigurationEventHandler*) NULL, RegistrationMode_ReplaceAll, Cleanup_None); 
    cout << "Using device " << camera.GetDeviceInfo().GetModelName() << endl; 
    } 
} 

:次のコードは、カメラソースを取得するために使用することができます。それが動作を確認するには、ここではそれにリンクし、すべてが動作している確認し、基本的なCプログラムがあります:

void basler_init(); 

int main() { 
    basler_init(); 
} 

私はこれをコンパイルして実行します。

$ gcc Test2.c -lbasler -Llib -Wl,--enable-new-dtags -Wl,-rpath,pylon5/lib64 -Wl,-E -lpylonbase -o Test2-c 

$ PYLON_CAMEMU=1 LD_LIBRARY_PATH=lib ./Test2-c 
Using device Emulation 

これは、予想される出力です。

しかし、これをHaskellで試してみると、動作が変わり、プログラムは無期限にブロックされます。ここではHaskellのソースコードがあります:私はコンパイルして、これを実行する

{-# LANGUAGE ForeignFunctionInterface #-} 

foreign import ccall "basler_init" baslerInit :: IO() 

main :: IO() 
main = baslerInit 

:アプリケーションを

$ ghc --make Test2.hs -o Test2-haskell -Llib -lbasler -optl-Wl,--enable-new-dtags -optl-Wl,-rpath,pylon5/lib64 -optl-Wl,-E -lpylonbase 

$ PYLON_CAMEMU=1 LD_LIBRARY_PATH=lib ./Test2-haskell 

は現在無期限にハングアップします。

私はstraceを実行して何が起こっているのかを知るために走っていますが、実際にはそれほど意識していません。 Haskellのアプリケーションのためのhttps://gist.github.com/ocharles/001b5f42c09229bc7a8482a22cadf486

  • strace出力:Cアプリケーションの

    の上に出力がここで追加が、これら2つのペーストを参照してくださいすることが長すぎますそれで、私はgdbを使って、Haskellアプリケーションがどこに行き詰まっているのかを確かめました:

    $ PYLON_CAMEMU=1 LD_LIBRARY_PATH=lib gdb Test2-haskell 
    GNU gdb (GDB) 7.11 
    Copyright (C) 2016 Free Software Foundation, Inc. 
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 
    This is free software: you are free to change and redistribute it. 
    There is NO WARRANTY, to the extent permitted by law. Type "show copying" 
    and "show warranty" for details. 
    This GDB was configured as "x86_64-pc-linux-gnu". 
    Type "show configuration" for configuration details. 
    For bug reporting instructions, please see: 
    <http://www.gnu.org/software/gdb/bugs/>. 
    Find the GDB manual and other documentation resources online at: 
    <http://www.gnu.org/software/gdb/documentation/>. 
    For help, type "help". 
    Type "apropos word" to search for commands related to "word"... 
    Reading symbols from Test2-haskell...done. 
    (gdb) run 
    Starting program: /home/ollie/work/circuithub/receiving-station/Test2-haskell 
    warning: File "/nix/store/9ljgbhb26ca0j9shwh8bwsa77h42izr2-gcc-5.4.0-lib/lib/libstdc++.so.6.0.21-gdb.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load". 
    To enable execution of this file add 
         add-auto-load-safe-path /nix/store/9ljgbhb26ca0j9shwh8bwsa77h42izr2-gcc-5.4.0-lib/lib/libstdc++.so.6.0.21-gdb.py 
    line to your configuration file "/home/ollie/.gdbinit". 
    To completely disable this security protection add 
         set auto-load safe-path/
    line to your configuration file "/home/ollie/.gdbinit". 
    For more information about this security protection see the 
    "Auto-loading safe path" section in the GDB manual. E.g., run from the shell: 
         info "(gdb)Auto-loading safe path" 
    [Thread debugging using libthread_db enabled] 
    Using host libthread_db library "/nix/store/bb32xf954imhdrzn7j8h82xs1bx7p3fr-glibc-2.23/lib/libthread_db.so.1". 
    ^C 
    Program received signal SIGINT, Interrupt. 
    0x00007ffff6c6fb33 in __recvfrom_nocancel() from /nix/store/98s2znxww6x7h2ch7cj1w5givahxmdna-glibc-2.23/lib/libc.so.6 
    (gdb) bt 
    #0 0x00007ffff6c6fb33 in __recvfrom_nocancel() from /nix/store/98s2znxww6x7h2ch7cj1w5givahxmdna-glibc-2.23/lib/libc.so.6 
    #1 0x00007fffedb885c2 in GxImp::CEnumCollector::OnReady(unsigned int, _GX_SOCKET_INTERFACE_INFO const*)() from /home/ollie/work/circuithub/receiving-station/pylon5/lib64/libgxapi-5.0.1.so 
    #2 0x00007fffedb8d54d in CCollector::Collect(GxImp::CSocket*, unsigned int, unsigned int, _GX_SOCKET_INTERFACE_INFO const*)() from /home/ollie/work/circuithub/receiving-station/pylon5/lib64/libgxapi-5.0.1.so 
    #3 0x00007fffedb8817b in CBroadcastSocketCollection::Collect(CCollector&, unsigned int)() from /home/ollie/work/circuithub/receiving-station/pylon5/lib64/libgxapi-5.0.1.so 
    #4 0x00007fffedb889ab in Gx::Enumerator::Discover(Gx::Enumerator::Callee*, unsigned int, unsigned int, sockaddr const*)() from /home/ollie/work/circuithub/receiving-station/pylon5/lib64/libgxapi-5.0.1.so 
    #5 0x00007fffeddeaca0 in Pylon::CBaslerGigETl::DoDeviceEnumeration(Pylon::DeviceInfoList&, bool, sockaddr const*)() from pylon5/lib64/libpylon_TL_gige-5.0.1.so 
    #6 0x00007fffeddeaebc in Pylon::CBaslerGigETl::InternalEnumerateDevices(Pylon::DeviceInfoList&)() from pylon5/lib64/libpylon_TL_gige-5.0.1.so 
    #7 0x00007fffeddf3c99 in Pylon::CTransportLayerBase<Pylon::IGigETransportLayer>::EnumerateDevices(Pylon::DeviceInfoList&, Pylon::DeviceInfoList const&, bool)() from pylon5/lib64/libpylon_TL_gige-5.0.1.so 
    #8 0x00007ffff7949669 in Pylon::CTlFactory::EnumerateDevices(Pylon::DeviceInfoList&, Pylon::DeviceInfoList const&, bool)() from pylon5/lib64/libpylonbase-5.0.1.so 
    #9 0x00007ffff7949c8f in Pylon::CTlFactory::InternalCreateDevice(Pylon::CDeviceInfo const&, GenICam_3_0_Basler_pylon_v5_0::gcstring_vector const&, bool)() from pylon5/lib64/libpylonbase-5.0.1.so 
    #10 0x00007ffff794a655 in Pylon::CTlFactory::CreateFirstDevice(Pylon::CDeviceInfo const&)() from pylon5/lib64/libpylonbase-5.0.1.so 
    #11 0x00007ffff7bd7dc5 in basler_init() from lib/libbasler.so 
    #12 0x0000000000438415 in rFl_info() 
    #13 0x0000000000000000 in ??() 
    

    Cプログラムの場合:

    Reading symbols from Test2-c...done. 
    (gdb) run 
    Starting program: /home/ollie/work/circuithub/receiving-station/Test2-c 
    warning: File "/nix/store/9ljgbhb26ca0j9shwh8bwsa77h42izr2-gcc-5.4.0-lib/lib/libstdc++.so.6.0.21-gdb.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load". 
    To enable execution of this file add 
         add-auto-load-safe-path /nix/store/9ljgbhb26ca0j9shwh8bwsa77h42izr2-gcc-5.4.0-lib/lib/libstdc++.so.6.0.21-gdb.py 
    line to your configuration file "/home/ollie/.gdbinit". 
    To completely disable this security protection add 
         set auto-load safe-path/
    line to your configuration file "/home/ollie/.gdbinit". 
    For more information about this security protection see the 
    "Auto-loading safe path" section in the GDB manual. E.g., run from the shell: 
         info "(gdb)Auto-loading safe path" 
    [Thread debugging using libthread_db enabled] 
    Using host libthread_db library "/nix/store/bb32xf954imhdrzn7j8h82xs1bx7p3fr-glibc-2.23/lib/libthread_db.so.1". 
    [New Thread 0x7fffed4ae700 (LWP 13792)] 
    [New Thread 0x7fffeccad700 (LWP 13793)] 
    Using device Emulation 
    [Thread 0x7fffeccad700 (LWP 13793) exited] 
    [Thread 0x7fffed4ae700 (LWP 13792) exited] 
    [Inferior 1 (process 13788) exited normally] 
    

    私の推測では、GHCのランタイムがpthreadsのは、異なる動作を持つようになり、何かをやっているですが、私はそれが何ができるかわかりません。私はこのTRACの解説が適切であると考えてい

  • +0

    違いはありません。潜在的な修正のために

    は、どのようにMySQLのパッケージの実装とblock_rts_signals()unblock_rts_signals()マクロを使用して見ています。私は 'cout'を' basler_init'の初期段階で問題なく使用することもできます。 – ocharles

    答えて

    8

    https://ghc.haskell.org/trac/ghc/wiki/Commentary/Rts/Signals

    違いは、Haskellのstraceの出力のライン495対Cのstraceの出力 にライン437を開始起こります。

    この時点で、ライブラリは2つのUDPソケットを作成し、2つのUDPデータグラム (448-449行/ 506-507 Haskell行)を送信します。パケットは、ローカルネットワーク192.168.1.0/24と192.168.56.0/24の2つのローカルネットワーク にブロードキャストされます。

    次に、(明らかに) の25マイクロ秒(行450C /行508ハスケル)のタイムアウトでこれらのソケットのいずれかで応答を待ちます。 Cの場合、選択コール がタイムアウトします。ハスケルの場合、選択呼び出しは、 によって中断され、GHC RTSによって使用されるSIGVTALRM信号が繰り返し割り込みされます。これは上記のTRAC解説に示されている同じパターン です。 J.J.Hakala @

    +3

    うわー、にスポット!私はhttp://www.serpentine.com/blog/2010/09/04/dealing-with-fragile-c-libraries-e-g-mysql-from-haskell/から「ハック」を使用しました。ありがとうございました! – ocharles

    関連する問題