2012-03-26 40 views
2

我正在做兩個框架(OpenSceneGraph和wxWidgets)之間的內存中圖像轉換。不想關心底層類(osg::ImagewxImage),我用的是面向流的I/O功能都API提供了像這樣:基於std :: vector創建std :: stringbuf <char>

1)創建std::stringstream

2)寫入使用流OSG的作家

3)使用wxWigdets讀者

這工作得相當好從流中讀取。到目前爲止,我一直使用直接訪問流緩衝區,但最近我的注意力被std::stringstream的「非連續底層緩衝區」問題所捕獲。我一直在使用kludge來獲得一個const char* ptr到緩衝區 - 但它工作(在Windows,Linux和OSX上使用MSVC 9和GCC 4.x進行測試),所以我從來沒有修復它。

現在我明白,這段代碼是一個定時炸彈,我想擺脫它。這個問題已經在SO(here for instance)上提出過好幾次了,但是我找不到能夠幫助我做最簡單的事情的答案。

我認爲最合理的做法是在後臺使用矢量創建自己的streambuf - 這可以保證緩衝區是連續的。我知道,這將不是一個通用的解決方案,但給我的限制:

1)所需的大小是無限,實際上相當明確

2)我流真正需要的是一個std::iostream(我不能使用原始字符數組)因爲API

任何人都知道我可以如何使用一個字符向量的自定義字符串?請不要回答「使用std::stringstream::str()」,因爲我知道我們可以,但我正在尋找其他東西(即使您認爲複製2-3 MB太快,我甚至不會注意到差異,讓我們考慮一下,我仍然對自定義stringbufs感興趣,只是爲了練習的美麗)。

回答

3

如果你可以只使用一個istreamostream(而不是 雙向),並且不需要尋找,這是很簡單的(代碼10 線)使用std::vector<char>創建自己的streambuf。 但是,除非字符串非常非常大,爲什麼呢? C++ 11標準 保證std::string是連續的;那 得到的&myString[0]可以用來作爲C風格的數組。「並且 之所以加上C++ 11的這個保證,是爲了認識現有的 的做法;那裏根本沒有任何實現,這不是 的情況(現在,它是必需的,在未來不會有任何實現在 的情況下)。

+0

我不確定我是否理解您的答案。關於僅使用istream/ostream:一個插件需要看到一個ostream,而另一個需要看到一個ostream。也許我可以使用相同的基礎矢量構建其中的每一個?關於使用std :: string:好的,但是如何從字符串中創建流? – Tibo 2012-03-26 08:57:32

+0

@如果一個插件需要一個ostream,另一個需要一個istream,那麼你可能不得不做一些雙向的事情。或者,如果他們不同時需要它們,則先使用相同的緩衝區先創建一個ostream,然後創建istream。至於流出字符串的流:'std :: [io] stringstream'已經存在。 – 2012-03-26 09:47:25

+0

您的意思是說,根據C++ 11,std :: stringstream的緩衝區保證是連續的嗎?無處可以讀取std :: stringstreams內部使用std :: strings - 任何指針? – Tibo 2012-03-26 11:41:25

1

boost :: iostreams有一些現成的接收器。有array_sink,如果你有某種上限,可以預先分配塊,這樣一個接收器不會動態增長,但另一方面,也可以是積極的。還有back_inserter_device,這是更通用的,並與std::vector直接工作。使用back_inserter_device的示例:

#include <string> 
#include <iostream> 
#include "boost/iostreams/stream_buffer.hpp" 
#include "boost/iostreams/device/back_inserter.hpp" 
int main() 
{ 
    std::string destination; 
    destination.reserve(1024); 
    boost::iostreams::stream_buffer< boost::iostreams::back_insert_device<std::string> > outBuff((destination)); 
    std::streambuf* cur = std::cout.rdbuf(&outBuff); 
    std::cout << "Hello!" << std::endl; 
    // If we used array_sink we'd need to use tellp here to retrieve how much we've actually written, and don't forgot to flush if you don't end with an endl! 
    std::cout.rdbuf(cur); 
    std::cout << destination; 
} 
+0

謝謝。我沒有在這個項目中使用增強功能,但會將您的解決方案放在枕頭之下供未來使用。 – Tibo 2012-03-26 11:38:39

相關問題