繁体   English   中英

将C#中的String []转换为C ++中的Char * []

[英]Convert a String[] in C# to a Char *[] in C++

我当前正在使用Visual Studio2010。这是我第一次为C ++类编写包装。 C ++中的类如下所示:

bool exampleCode(char* arrayOfStrings[], int number, char* regularString)

我创建的头文件如下所示:

bool exampleCode(array<String^>^ arrayOfStrings, int number, String^ regularString)

.cpp文件类如下所示:

bool exampleCode(array<String^>^ arrayOfStrings, int number, System::String^ regularString)

我想出了如何封送RegularString数据,但不确定如何将String数组转换为char*[] 任何帮助,将不胜感激。

以下是理想的高效(最小复制)和异常安全的消息:

#include <algorithm>
#include <memory>
#include <vector>

using System::IntPtr;
using System::String;
using System::Runtime::InteropServices::Marshal;

bool exampleCodeManaged(array<String^>^ arrayOfStrings, String^ regularString)
{
    auto deleter = [](char* p) { Marshal::FreeHGlobal(IntPtr(p)); };
    typedef std::unique_ptr<char[], decltype(deleter)> cstr_t;
    auto make_cstr = [&deleter](String^ s)
    {
        return cstr_t(
            static_cast<char*>(Marshal::StringToHGlobalAnsi(s).ToPointer()),
            deleter
        );
    };

    std::vector<cstr_t> cstrs;
    cstrs.reserve(arrayOfStrings->Length);
    for each (String^ s in arrayOfStrings)
        cstrs.push_back(make_cstr(s));

    std::vector<char*> ptrs;
    ptrs.reserve(cstrs.size());
    std::for_each(
        cstrs.begin(),
        cstrs.end(),
        [&ptrs](cstr_t& cstr) { ptrs.push_back(cstr.get()); }
    );

    auto reg_cstr = make_cstr(regularString);

    return exampleCode(ptrs.data(), arrayOfStrings->Length, reg_cstr.get());
}

(请注意, number并不需要传递中,因为它可以从数组的长度推断的管理功能。)

或者,结合Ben Voigt的建议使用std::string代替Marshal类:

#include <algorithm>
#include <string>
#include <vector>
#include <msclr/marshal_cppstd.h>

using System::String;

bool exampleCodeManaged(array<String^>^ arrayOfStrings, String^ regularString)
{
    using msclr::interop::marshal_as;

    std::vector<std::string> strs;
    strs.reserve(arrayOfStrings->Length);
    for each (String^ s in arrayOfStrings)
        strs.push_back(marshal_as<std::string>(s));

    std::vector<char*> ptrs;
    ptrs.reserve(strs.size());
    std::for_each(
        strs.begin(),
        strs.end(),
        [&ptrs](std::string& s) { ptrs.push_back(&s[0]); }
    );

    auto reg = marshal_as<std::string>(regularString);

    return exampleCode(ptrs.data(), arrayOfStrings->Length, &reg[0]);
}

这是一个易于重用的版本(带有演示),它通过减少分配数量和改善局部性来改进@ildjarn的答案。 它还使用您选择的编码,例如UTF-8。

#include <iostream>
#include <vector>

#include <windows.h>
#include <vcclr.h>

using namespace System;

template <typename T>
struct advanced_marshal;

template <>
struct advanced_marshal<char*[]>
{
    char** get() { return &m_strings[0]; }

    advanced_marshal( array<System::String^>^ strings, UINT code_page = CP_ACP ) : m_strings(strings->Length)
    {
        if (int count = strings->Length) {
            int i;
            size_t total_length_estimate = count; // one NUL byte per string
            for( i = 0; i < count; ++i ) {
                total_length_estimate += strings[i]->Length * 4;
            }

            m_buffer.resize(total_length_estimate);
            auto tail = m_buffer.begin(), end = m_buffer.end();
            i = 0;
            do {
                m_strings[i] = &*tail;
                pin_ptr<const WCHAR> pwsz = PtrToStringChars(strings[i]);
                tail += 1 + WideCharToMultiByte(code_page, 0, pwsz, strings[i]->Length, &*tail , end - tail, nullptr, nullptr);

                ++i;
            } while (i < count);
        }
    }

    advanced_marshal(advanced_marshal<char*[]>&& other) { m_buffer.swap(other.m_buffer); m_strings.swap(other.m_strings); }

private:
    advanced_marshal(const advanced_marshal<char*[]>&); // = delete
    void operator=(const advanced_marshal<char*[]>&); // = delete

    std::vector<char> m_buffer;
    std::vector<char*> m_strings;
};

void print_some_strings( char* strings[], int num )
{
    for( int i = 0; i < num; ++i )
        std::cout << strings[i] << "\n";

    std::cin.get();
}

int main(array<System::String ^> ^args)
{
    print_some_strings(advanced_marshal<char*[]>(args).get(), args->Length);
    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM