2017-07-27 46 views
1

我想要cythonize的SFML庫定義了下面的這個函數,它允許更改錯誤的打印位置(默認情況下,SFML在未調用此函數時將錯誤消息寫入控制檯):無法重定向來自Cython的錯誤流

namespace sf { 
    std::ostream& err() { 
     static DefaultErrStreamBuf buffer; 
     static std::ostream stream(&buffer); 
     return stream; 
    } 
} 

對於上述功能簡化我的文件.pxd:

cdef extern from 'SFML/System.hpp' namespace 'sf': 
    ostream& cerr 'sf::err'() 

而且我.pyx模塊,它編譯並運行正常,但不重定向錯誤消息(他們仍然打印到控制檯)。

cdef void set_error_handler(): 
    cerr().rdbuf(NULL) # This call should prevent errors appearing in the console but it silently fails 

set_error_handler() 

我正在使用MSVC和靜態鏈接到C++代碼。

編輯

下面是例子,如何在自己的代碼中SFML庫記錄錯誤(full source):

... 
// Error, failed to load the image 
err() << "Failed to load image \"" << filename << "\". Reason: " << stbi_failure_reason() << std::endl; 
... 

我的目標是出現在抑制像上面這樣一個錯誤信息控制檯,並最終將它們重定向到自己的緩衝區中。

+0

你能提供一個最小的pyx文件,你實際上使用日誌? – ead

+0

@ead當然,我已經更新了這個問題。我不會將任何內容記錄到'sf:err()'中,SFML庫會執行此操作,我想要禁止該操作或重定向。 – HankMoody

+0

如果在C++中編寫'set_error_handler()'並從cython調用它,會發生什麼情況。那它有用嗎?只是試圖排除,這是一個不是一個問題。 – ead

回答

1

有兩種成分可以解決您的問題,兩種成分都在您的設置文件中。

第一成分是您有兩個擴展名:

ext_modules = [ 
    Extension('nebula.sfml.system', ['nebula/sfml/system.pyx'], 
       language='c++', ...), 
    Extension('nebula.sfml.graphics', ['nebula/sfml/graphics.pyx'], 
       language='c++', ...), 
] 

這意味着用Cython將創建兩個不同的共享庫:system.dllgraphics.dll由蟒這將在兩個裝載以後動態。

第二個組成部分:sfml -library靜態鏈接,但包含一個singleton(問題中的錯誤流),這是一個災難的祕訣:使用您的設置,它不再是單身人士,但有兩個不同的錯誤流:來自system.dll的錯誤流和來自graphics.dll的錯誤流。因此,您正在沉默來自system.dll的錯誤流(因爲您的電話set_error_handler()居住在那裏),但是寫入來自graphics.dll(此處爲image_load_test住)的錯誤流。

那麼可以做些什麼?有兩個選項:

  1. 使用共享sfml -libraries(至少sfml-system-s),因此單會留一個單例。
  2. 將兩個pyx文件的內容放在同一個pyx-file/Extension /共享庫中。至少現在,system.pyx的內容僅適用於graphics.pyx
+0

不幸的是,它不起作用,Cython抱怨「C++引用無法聲明;改用指針」。所以我使用了像'cdef ostream * ref_to_err =&cerr()'這樣的指針代替引用,它顯然已經被編譯了,但它也沒有工作。 – HankMoody

+0

@PythonFanboy請你提供一個你的設置的最簡單的例子嗎?所以我可以重現這個問題? – ead

+0

好的,我已經在這裏上傳了:https://www.dropbox.com/s/svf8o5o9o5mkt9m/sfml_error.zip?dl=0 – HankMoody