views:

684

answers:

2

In an attempt to wrap some unmanaged code in a managed .dll I'm trying to convert a Generic::List of data points into a std::vector. Here's a snippet of what I'm trying to do:

namespace ManagedDLL
{
    public ref class CppClass
    {
        void ListToStdVec( const List<double>& input_list, std::vector<double>& output_vector )
        {
            // Copy the contents of the input list into the vector
            // ...
        }

        void ProcessData( List<double> sampleData )
        {
            std::vector<double> myVec;

            ListToStdVec( sampleData, myVec );

            // Now call the unmanaged code with the new vector
            // ...
        }
    }
}

Compiling this gives me:

error C3699: '&' : cannot use this indirection on type 'const System::Collections::Generic::List'

I've probably missed something fundamental here (I'm relatively new to .net's way of doing things), but that looks like reasonably valid code to me.. ?

[Edit] I've tried both Andy and Dario's suggestions and they work, but how do I then access the members of the input list? I've tried all sorts of combinations of dreferencing and nothing seems to compile:

void ListToStdVec( const List<double>% input_list, std::vector<double>& output_vector )
{
    int num_of_elements = input_list->Count;
}

void ListToStdVec( const List<double>^ input_list, std::vector<double>& output_vector )
{
    int num_of_elements = input_list.Count;
}

...both give me:

error C2662: 'System::Collections::Generic::List::Count::get' : cannot convert 'this' pointer from 'const System::Collections::Generic::List' to 'System::Collections::Generic::List %'

...so how do you access the reference / pointer?

+1  A: 

As List<T> is a managed .NET class, it's passed by managed GC-Handle denoted by ^ and not by C++-reference.

Ex:

void ListToVec(List<double>^ input_list, std::vector<double>& out)

You don't need additional const here. The notation List<T>^% creates a tracking reference (comparable to C++-pointers) rather than a call by reference. Just access the members by list->... and list[...].

Dario
Removing the const does indeed allow me to access input_list's members, but I like to make inputs const wherever possible as it often catches mistakes at compile time.
Jon Cage
+2  A: 

According to Herb Sutter, % is the managed object pass by reference character. Convert the code to the following, and it should work:

void ListToStdVec( const List<double>% input_list, std::vector<double>& output_vector
{
    // Copy the contents of the input list into the vector
    // ...
}

Edit: I think the const is causing the issues, although I'm not sure why. If you change the List argument to not be const, then the first function will compile if you use the -> operator, while the second function will compile if you use the . operator (I'm not sure why that difference exists - it doesn't make much sense).

That said, if all that you want to do is to copy the elements in the List to the vector, then you really want to use ^. Think of that as having a reference to the managed object. I think that % would be used if you want to pass the reference "by reference" (i.e. reassign input_list to something else within ListToStdVec(), and have the caller see the result of that assignment. However, given that you use the . operator to access members when using %, that tells me that I may not understand the purpose of that at all.

Andy
% behaves more like a pointer than like a reference!
Dario
If that's true the why does input_list->Count work for the ^ operator and input_list.Count work for the % operator? Tradionally that would indicate the opposite (speaking from a C++ perspective)?
Jon Cage
r.e. your edit; I'd come to the same conclusion and am just as mistified :-)
Jon Cage