views:

38

answers:

1

This is a Windows Forms Application project using Visual Studio 2010. That being said:

I've an unmanaged 'Vector' implementation, something like:

template<class T>
class Vector {
public:
    T* data;
    unsigned len;

    (...constructors and operators overloading like =, [], == and !=)
};

It works great. I've done several tests before with it. After that I've implemented an also unmanaged 'Matrix' that uses the previously class Vector. Something like:

template<class T>
class Matrix : public Vector<Vector<T>*> {

public:
    Matrix(unsigned height = 20, unsigned width = 20) 
    : Vector(height) 
    {
    for (unsigned i = 0; i < height; i++) {
            data[i] = new Vector<T>(width);
        }
    }

    Vector<T> operator[](unsigned pos) {
        return data[pos];
    }
};

It also works great but with unmanaged data as T. My main objective, access data using [][], worked as expected.

But now I want to use this Matrix class inside managed code, with data T also being managed code, in this case a 'Cell' already implemented:

public ref class Cell {
public:
    bool dead;

public:
    Cell() {
        this->dead = false;
    }
    Cell(bool dead) {
        this->dead = dead;
    }

    virtual String^ ToString() override {
        return (this->dead ? "0" : "1");
    }
};

I'm doing the initialization this way:

Matrix<gcroot<Cell^>>* cells = new Matrix<gcroot<Cell^>>(height, width);

for (unsigned i = 0; i < height; i++) {
    for (unsigned j = 0; j < width; j++) {
        gcroot<Cell^> * cell = new gcroot<Cell^>;
        cells[i][j] = cell; // ERROR!!
    }
}

The line where I assign the cell to matrix always returns the error in the title. Other operators (aside from '=') also gives me the same error.

I've tried everything but I can't find a way to fix this. I'm really avoiding to touch Vector and Matrix classes because they've to be unmanaged and I've to use gcroot to inject managed data inside it.

At the end of the day, Cell will be a System::Windows::Forms::Button so the implementation has to be this way.

Any ideas? Sorry if I was unable to explain myself. If you need more code from Vector class please tell. Thanks is advanced :)

A: 

Honestly, you are going to have to do a lot of work to use this native C++ code direct from managed code (if it's even possible).

It's probably going to be easier to reimplement it in STL/CLR, if you need to stick with C++, or in C# if not. The mere existence of this STL/CLR class library should tell you something about how advisable it is to use native C++ STL containers in this way.

EDIT: You can probably fix the compilation error by using

template<class T> class Matrix : public Vector<Vector<T>>

Your operator[] should not return by value, or the underlying Vector element will not be altered as you will be working with a copy of what's in the Matrix.

Vector<T>& operator[](unsigned pos) {

Comments about this being non-trivial stand.

Steve Townsend
This is for a class project really and I've been taught that it's pretty straight forward just using gcroot. Why would it be that difficult?
Jota
It's difficult because of different memory management assumptions in the native and managed worlds. Perhaps what you were taught was intended as general guidance on managed/native interop, and not specific to use of STL containers from the managed world?
Steve Townsend
Yes, this is a multiple stages work for us to learn native/managed interop. He implemented Vector and Matrix at a earlier stage and now we should both to hold a bi-dimensional array of Buttons and that is it. The only native code here is Vector and Matrix and we're not supposed to use STL/CLR. If you say that it sin't the best approach to this problem, I agree with you, but thats how we should implement it.
Jota
@Jota - then it's important to understand that blanket guidance you have received that 'this is pretty straight forward' is an oversimplification. Calling a Win32 C API via P/Invoke is pretty straight forward - direct usage of C++ STL containers from C# is not. Compare your project with what others are doing. Typically, complex interop scenarios involve wrapping the native code as a COM object, which while non-trivial is at least the mainstream interop implementation path. Usage of C++ classes (let alone class templates like STL) from C# while supported, is an edge case.
Steve Townsend
That's not C# is C++ .NET but the problem is the same right?
Jota
@Jota - yes, memory management is still difficult. When you pass a managed variable to a native code container you have to make sure that the GC does not move the managed object. Otherwise the native code will crash as it expects invariant memory location for objects it uses. Check out my EDIT, your code has some issues anyway.
Steve Townsend
Well, the error remains. It must be deeper than that. I know its stupid, I know I shouldn't be doing it this way but that's what we're asked to do. I'll try to at least bypass the error or give up from this approach at all!
Jota