2

OS : xp
IDE : VS 2008
In the project that i'm doing in visual C++ i have declared a std::vector inside managed class as so

std::vector<pts> dataPoints;//this gives error c4368 : mixed type not allowed 

but this works

std::vector<pts> * dataPoints;//a pointer to the vector  

i then have created this vector on the free store as so in the constructor of the managed class

dataPoints = new std::vector<pts>(noOfElements,pts());//which is not so attractive.

the reason i need vector is because there is file that i'm reading through the ifstream and storing those values in the vector.
Q1) why is that i'm able to declare a pointer to object of native type(i guess)but not an object? furthermore, prior to trying vector i tried the managed array as so

cli::array<Point> dataPoints //and i defined it later.

but when i do this

ifile >> dataPoints[i].X;   

it gives an error c2678 : operator= is not overloaded for int!!.
Q2) why is it that i cant use a managed code here. At first i thought it might be a wrapper class Int but then autounboxing(conversion operators) should take care of it?or is it that Point::X is qualified with property and thus is not recognized as normal int? what am i missing?. this is the reason i went for vector and pts solution.
pts is as follows

 struct pts
{
  int X, int Y;
  pts() : X(0),Y(0){}
  pts(int x,int y) : X(x),Y(y){}
};//this i created to store the data from the file.
Koushik Shetty
  • 2,146
  • 4
  • 20
  • 31
  • 1
    [mixed-management-in-c++](http://stackoverflow.com/questions/9283383/mixed-management-in-c) – yngccc Apr 19 '13 at 18:11

2 Answers2

5

An important property of managed class objects is that they get moved by the garbage collector. This happens when it compacts the heap. That plays havoc with native C++ objects, pointers to their members will become invalid. So as a rule, the compiler forbids embedding a native non-POD object inside a managed one. A pointer is not a problem.

The exact same problem exists for your use of the >> operator. The int gets passed by reference to operator>>(). Disaster strikes if the garbage collector kicks in right between the code taking the reference of the int and calling the operator. A simple workaround for that one is an intermediate step through a local variable:

int x;
ifile >> x;
dataPoint[i].X = x;

Which works because local variables are stable and are not subject to garbage collection.

None of this is a problem in native code. Do keep in mind that your ref class can easily call a native function. So separating the two can be useful and/or necessary.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • yes instead of the local variable i used the vector and then loaded the data into it. this worked. but one question remains is why is the error`c2678` for `>>` should it not be mixed type error? – Koushik Shetty Apr 19 '13 at 19:40
  • Error messages for these kind of problems are not always stellar. Do note the MSDN Library article for C2678. Quote: "C2678 can occur if you do not pin a native member before calling a member function on it" – Hans Passant Apr 19 '13 at 20:16
1

You can't directly contain a native type within a managed type: this is just a restriction on C++/CLI. I'm thinking this might be to do with the possibilities of pointers within the native type. If the native type is directly within the managed type, then when managed objects get shuffled around during garbage collection, then these pointers would point to the original, now incorrect, memory.

Therefore the native object needs to be on the heap, so that its internals don't get changed by garbage collection. So you need to hold the vector as a pointer, and delete it appropriately. Note that the latter isn't entirely trivial, and you need to have some knowledge of C++/CLI (which differs subtly from C#). See http://msdn.microsoft.com/en-us/library/ms177197(v=vs.100).aspx.

Looking at the last time I did this, in my file I had

public:
    !NetClass();
    ~NetClass() { this->!NetClass(); } // avoid arning C4461
private:
    class NativeImpl* const m_pImpl; // can't contain NativeImpldirectly

And in the cpp file I had

NetClass::!NetClass()
{
    // implement finalizer in ref class
    delete m_pImpl;
}

You might just want to use the pimpl idiom here if you have more than one native class to contain. See Why should the "PIMPL" idiom be used?.

Finally, I last did this quite a while ago, and I'm just saying what worked for me at the time. If you're doing this, you really need to know what you're doing. I used a book called C++/CLI in Action, which I'd recommend.

Edit

This article on STL/CLR looks interesting: http://blogs.msdn.com/b/nikolad/archive/2006/06/16/stlclr-intro.aspx. To quote

STL/CLR, originally called STL.NET, is an implementation of Standard Template Library (STL) that can operate with objects of managed types. VC++ already has implementation of STL, however it is currently working only with native types.

(I can't really help on your Q2)

Community
  • 1
  • 1
TooTone
  • 7,129
  • 5
  • 34
  • 60
  • firstly since i'm calling `new` on the unmanaged code i should `delete` this in the finalizer instead of the managed class's destructor right?. secondly if i declare a object of native type it should be allocated on the stack and hence not movable right? – Koushik Shetty Apr 19 '13 at 19:01
  • yes, see the msdn link for deleting in the finalizer (confusingly "A Visual C++ finalizer is not the same as the Finalize method (common language runtime documentation uses finalizer and the Finalize method synonymously)."). I think you're ok to declare objects of native type on the stack. – TooTone Apr 19 '13 at 19:11