我想讓一個DLL公開某個API,因此想實現一個安全的方式來複制DLL邊界上的字符串。 DLL實現非常簡單 - 所有返回字符串值的函數都帶有兩個參數 - char*
和size_t&
。如果大小足夠大,則將DLL內部字符串的內容寫入給定指針,將大小設置爲實際大小並返回成功的返回碼。如果不是,我將它的大小設置爲它應該返回的錯誤代碼。 DLL方面非常簡單。通過DLL邊界複製安全字符串
現在更復雜 - 如何製作一個很好的模板函數,該函數給出指向DLL中某個函數的指針將執行所有正確的操作來填充std::string
的實例。這是我來到了:
template<typename I>
CErrorCode GetStringValue(const I& Instance, CErrorCode(I::*pMethod)(char*, size_t&) const, std::string& sValue)
{
std::string sTemporaryValue;
size_t nValueLength = sTemporaryValue.capacity();
sTemporaryValue.resize(nValueLength);
do
{
auto eErrorCode = (Instance.*pMethod)(const_cast<char*>(sTemporaryValue.c_str()), nValueLength);
if (eErrorCode == CErrorCode::BufferTooSmall)
{
sTemporaryValue.resize(nValueLength);
}
else
{
if (eErrorCode == CErrorCode::NoError)
{
sTemporaryValue.resize(nValueLength);
sValue = std::move(sTemporaryValue);
}
return eErrorCode;
}
}
while (true);
}
所以我做了初步resize
,因爲我不能這樣做,第一個電話後(因爲那就刪除的內容,因爲該字符串最初是空的)。但resize
用零字符填充字符串,這會讓我感到不安(我的意思是我知道我將會自己做填充)。然後,即使在成功運行後,我也需要resize
,因爲如果長度實際上更小,我需要調整大小。任何建議,如果這可以做我更好的方式?
我會建議一個不同的設計模式:不是傳遞一個緩衝區和一個'size_t&'引用,傳遞一個函數指針和一個不透明的指針。 DLL調用函數指針,傳遞給它的字符串所需的'size_t'和不變的指針。函數指針負責分配足夠多的'char []',並返回一個指向它的指針。無需處理笨拙的'BufferTooSmall',並將其包裝到C++類中變得微不足道。 –
好吧,但如果我知道大多數時間所有的調用者都會使用'std :: string',那麼我在傳輸到字符串時會進行分配和複製。現在我有機會在第一次調用時填充值,從而只執行默認的'std :: string'構造函數中完成的內部分配。 –
沒有禁止實現將不透明指針轉換爲'std :: string *'的函數的規則,然後相應地調整它的大小並返回一個指向該字符串數據的指針,然後將一個指針傳遞給該函數,並將一個「std :: string',到你的DLL。 –