C++ 関数を使用して C ベースの関数を操作できるように、C と互換性のある (使いやすい) 戻り値の型を作成する必要があります。
wstring
のベクトルをwchar_t**
配列に変換するにはどうすればよいですか?
C++ 関数を使用して C ベースの関数を操作できるように、C と互換性のある (使いやすい) 戻り値の型を作成する必要があります。
wstring
のベクトルをwchar_t**
配列に変換するにはどうすればよいですか?
wstring ベクトルを反復処理して、それぞれwstring::c_str()
をwchart_t**
配列に追加できます。
wstring は basic_string のテンプレート化されたインスタンス化であるため、その c_str() 関数は wchar_t* を返します。
だから、あなたは次のようなことができます
std::vector<const wchar_t*> pointers;
pointers.reserve(wstrVec.size());
for (auto it = wstrVec.begin(); it != wstrVec.end(); ++it) {
pointers.push_back(it->c_str());
}
const whcar_t** cptr = pointers.data();
コンテキストがなければ、スコープ/ライフタイムの問題に対処する最善の方法をアドバイスすることは困難です。ライブラリを作成していますか (これは、スコープを制御できないことを示唆しています)、または監視している C コードからのコールバック用の API を提供していますか?
一般的なアプローチは、呼び出し元が適切なサイズの宛先バッファーを提供できるように、サイズ変更 API を提供することです。
size_t howManyWstrings()
{
return wstrVec.size();
}
bool getWstrings(const wchar_t** into, size_t intoSize /*in pointers*/)
{
const size_t vecSize = wstrVec.size();
if (intoSize < vecSize || into == nullptr)
return false;
for (size_t i = 0; i < vecSize; ++i) {
into[i] = wstrVec[i].c_str();
}
return true;
}
C関数がwchar_t
バッファへのポインタを期待しており、このポインタを移動できるように思えます。
これはほとんど簡単ですが、ポインターの有効期間を管理する必要があります。そのために、これを戻り値の型として行うのではなく(したがって、コードの正気は言うまでもなく、C が API を台無しにすることを許す)、C 関数の呼び出しサイトでこのロジックを実行することをお勧めします。
/** A function that produces your vector */
std::vector<wchar_t> foo();
/** The C function in question */
void theCFunction(wchar_t**);
int main()
{
std::vector<wchar_t> v = foo();
wchar_t* ptr = &v[0];
theCFunction(&ptr);
}
char
ところで、質問といくつかのコメントから、何と何を誤解してwchar_t
いるように聞こえます。それらはエンコーディング層の下にあり、UTF-8 を使用している場合は、UTF-8 文字列の各バイトを 1 バイトとして保存する必要があります。 . これはchar
、 のようにを使用することを意味しstd::string
ます。確かに、その文字列の個々のバイトが必ずしも 1 つの論理 Unicode 文字を表すとは限りませんが、それは重要ではありません。
可能であれば、これをまったく行わないようにすることをお勧めします。
本当に選択肢がない場合は、基本的に、ポインターの配列を割り当て、次に各文字列にスペースを割り当て、入力内の個々の文字列を割り当てたバッファーにコピーするようなことを行います。
wchar_t *dupe_string(std::wstring const &input) {
wchar_t *ret = new wchar_t[input.size()+1];
wcscpy(ret, input.c_str());
return ret;
}
wchar_t **ruin(std::vector<std::wstring> const &input) {
wchar_t **trash = new wchar_t*[input.size()];
for (int i=0; i<input.size(); i++)
trash[i] = dupe_string(input[i]);
return trash;
}
ただし、コメントに基づいて、これが現在の状況に適用されることについていくつかの懸念があります-これは、入力がワイド文字列であり、通常は UTF-16 または UTF-32/UCS-4 を意味することを前提としています。入力が実際に UTF-8 の形式である場合、扱うストレージ要素は実際にはchar
ではなくwchar_t
になるため、入力は ではなく狭い文字列 ( std::string
) であり、一致する出力char **
は ではありませんwchar_t **
。
のベクトルをstd::wstring
ベースのwchar_t**
文字列に変換する関数です。その DisposeBuffer(); を使用しているため、メモリリークもありません。他の回答とは異なります。
wchar_t ** xGramManipulator::GetCConvertedString(vector< wstring> const &input)
{
DisposeBuffer(); //This is to avoid memory leak for calling this function multiple times
cStringArraybuffer = new wchar_t*[input.size()]; //cStringArraybuffer is a member variable of type wchar_t**
for (int i = 0; i < input.size(); i++)
{
cStringArraybuffer[i] = new wchar_t[input[i].size()+1];
wcscpy_s(cStringArraybuffer[i], input[i].size() + 1, input[i].c_str());
cStringArraySize++;
}
return cStringArraybuffer;
}
これは、メモリ リークを回避するための DisposeBuffer ヘルパー関数です。
void xGramManipulator::DisposeBuffer(void)
{
for (size_t i = 0; i < cStringArraySize; i++)
{
delete [] cStringArraybuffer[i];
}
delete [] cStringArraybuffer;
cStringArraybuffer = nullptr;
cStringArraySize = 0;
}
そして、これらの前に、コンストラクターにダミー スペースを割り当てます。
xGramManipulator::xGramManipulator()
{
//allocating dummy array so that when we try to de-allocate it in GetCConvertedString(), dont encounter any undefined behavior
cStringArraybuffer = new wchar_t*[1];
cStringArraySize = 0;
for (int i = 0; i < 1; i++)
{
cStringArraybuffer[i] = new wchar_t[1 + 1];
cStringArraySize++;
}
}
そして、それはすべて完了です。