Следующее является идеально эффективным (минимальное копирование) и безопасным от исключений:
#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
не нужно передавать управляемой функции, так как это может быть выведено из длины массива.)
В качестве альтернативы можно включить предложение Бена Фойгта использовать 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]);
}