1

我需要创建一个与 C 兼容(友好)的返回类型,以便我的 C++ 函数可用于处理基于 C 的函数。

如何将向量转换为wstring数组wchar_t**

4

5 回答 5

2

您可以遍历 wstring 向量并将每个向量添加wstring::c_str()到您的wchart_t**数组中。

于 2013-07-29T05:56:23.510 回答
1

如果可能的话,最好避免这样做。

如果你真的别无选择,你基本上会做一些事情,比如分配一个指针数组,然后为每个字符串分配空间,并将输入中的每个单独的字符串复制到你分配的缓冲区。

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 **.

于 2013-07-29T05:56:39.780 回答
1

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;
}
于 2013-07-29T06:32:58.117 回答
1

听起来你的 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);
}

顺便说一句,从问题和一些评论中,听起来您误解了什么charwchar_t -它们位于编码层下方,如果您有 UTF-8,那么您应该将 UTF-8 字符串的每个字节存储为单个字节. 这意味着使用chars,就像在 a 中一样std::string。当然,该字符串中的每个单独的字节不一定代表一个逻辑 unicode 字符,但这不是重点。

于 2013-07-29T06:57:44.497 回答
0

这是用于将向量转换为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++;
    }
}

这一切都完成了。

于 2013-08-09T17:32:05.850 回答