特定のAPIを公開するDLLを作成しようとしています。そのため、DLL境界で文字列をコピーする安全な方法を実装する必要がありました。 DLL実装は非常に単純です。文字列値を返すすべての関数は、char*
とsize_t&
という2つの引数をとります。サイズが十分大きい場合は、memcpy
の文字列の内容をDLL内から指定されたポインタに移動し、サイズを実際のものに設定し、成功したリターンコードを返します。そうでない場合は、サイズをエラーコードに戻してください。 DLL側は非常に簡単です。DLL境界での安全な文字列のコピー
これ以上複雑なのは、DLLの関数へのポインタを指定した素敵なテンプレート関数を作成して、std::string
のインスタンスを記入するための正しい操作を行う方法です。私は最初の呼び出しの後に(文字列は、最初は空であるので、それ以来、それは、コンテンツを消去するだろう)ことはできませんので、だから私は、最初のresize
をした
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
が必要です。なぜなら、実際には長さが小さかったので、サイズを変更する必要があるからです。これは私がより良い方法で行うことができればどんな提案?
バッファと 'size_t& '参照を渡す代わりに、関数ポインタと不透明ポインタを渡す代わりに、別のデザインパターンを提案します。 DLLは関数ポインタを呼び出し、文字列に必要な 'size_t'と不透明なポインタをそのまま渡します。関数ポインタは、十分な 'char []'を割り当ててポインタを返します。不器用な 'BufferTooSmall'を扱う必要はなく、これをC++クラスにラップするのは簡単です。 –
まあ、しかし、私が知っていれば、すべての呼び出し元が 'std :: string'を使用することを知っていれば、文字列に転送するときに割り当てとコピーをしています。今度は、最初の呼び出し時に値を入力する部分的なチャンスを立てて、デフォルトの 'std :: string'コンストラクタで内部的な割り当てだけを行います。 –
不透明なポインタを 'std :: string *'に変換する関数を実装することを禁じる法律は存在せず、それに応じてサイズを変更して文字列のデータへのポインタを返し、ポインタをこの関数に渡し、 'std :: string'をDLLに追加します。 –