Конвертировать System::array в std::vector

Кто-нибудь знает какой-либо простой способ преобразовать CLI/.NET System:: массив в C++ std::vector, кроме того, чтобы сделать это поэлементно?

Я пишу метод-оболочку (SetLowerBoundsWrapper, ниже) в CLI/C++, который принимает массив System:: в качестве аргумента и передает эквивалентный std:: vector в собственный метод C++ (set_lower_bounds). В настоящее время я делаю это следующим образом:

using namespace System;

void SetLowerBoundsWrapper(array<double>^ lb)
{
    int n = lb->Length;
    std::vector<double> lower(n); //create a std::vector
    for(int i = 0; i<n ; i++)
    {
        lower[i] = lb[i];         //copy element-wise
    } 
    _opt->set_lower_bounds(lower);
}

1 ответ

Решение

Другой подход, позволяющий.NET BCL делать работу вместо стандартной библиотеки C++:

#include <vector>

void SetLowerBoundsWrapper(array<double>^ lb)
{
    using System::IntPtr;
    using System::Runtime::InteropServices::Marshal;

    std::vector<double> lower(lb->Length);
    Marshal::Copy(lb, 0, IntPtr(&lower[0]), lb->Length);
    _opt->set_lower_bounds(lower);
}

РЕДАКТИРОВАТЬ (в ответ на комментарии к ответу Конрада):

Следующие и компилируются для меня с VC++ 2010 SP1, и в точности эквивалентны:

#include <algorithm>
#include <vector>

void SetLowerBoundsWrapper(array<double>^ lb)
{
    std::vector<double> lower(lb->Length);
    {
        pin_ptr<double> pin(&lb[0]);
        double *first(pin), *last(pin + lb->Length);
        std::copy(first, last, lower.begin());
    }
    _opt->set_lower_bounds(lower);
}

void SetLowerBoundsWrapper2(array<double>^ lb)
{
    std::vector<double> lower(lb->Length);
    {
        pin_ptr<double> pin(&lb[0]);
        std::copy(
            static_cast<double*>(pin),
            static_cast<double*>(pin + lb->Length),
            lower.begin()
        );
    }
    _opt->set_lower_bounds(lower);
}

(Искусственная цель состоит в том, чтобы позволить pin_ptr открепить память как можно раньше, чтобы не мешать сборщику мусора.)

Мы видим в этом какие-то проблемы?

  #include <cstring>
  #include <vector>

  template<typename T>
  cli::array<T> ^ pincpy_a_v(std::vector<T> & v) {
     cli::array<T> ^ a(gcnew cli::array<T>(v.size()));
     pin_ptr<T> a_ptr = &a[0];
     std::memcpy(a_ptr, v.data(), v.size() * sizeof(T)); 
     return a;
  }

  template<typename T>
  std::vector<T> pincpy_v_a(cli::array<T> ^ a) {
     auto v{std::vector<T>(a->Length)};
     pin_ptr<T> a_ptr = &a[0];
     std::memcpy(v.data(), a_ptr, a->Length * sizeof(T)); 
     return v;
  }
Другие вопросы по тегам