[英]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, ®[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.