How do you create an array of pointers to managed types? (C++/CLI)

M

memeticvirus

I have an array cli::array<float, 2> and I would like to access a
subset of it's values by compiling an array of pointers. But, it's not
possible to create an array of type
cli:array<cli::interior_ptr<float>, 2>...

So, what do I do?
 
B

Ben Voigt [C++ MVP]

I have an array cli::array<float, 2> and I would like to access a
subset of it's values by compiling an array of pointers. But, it's not
possible to create an array of type
cli:array<cli::interior_ptr<float>, 2>...

So, what do I do?

I think interior_ptr is a native type so you'd use a normal C++ array (not
cli::array). You can make .NET arrays of tracking handles of course
(cli::array<T^, 2> where T is a .NET reference type).

Of course, you could store integer indices in the array instead of
interior_ptr.
 
M

memeticvirus

I think interior_ptr is a native type so you'd use a normal C++ array (not
cli::array). You can make .NET arrays of tracking handles of course
(cli::array<T^, 2> where T is a .NET reference type).

Of course, you could store integer indices in the array instead of
interior_ptr.

I've tried using an array of tracking handles like this...

cli::array<float ^, 2> ^handles;
cli::array<float, 2> ^data;

data = gcnew cli::array<float, 2>{
{0, 0},
{10, 10},
{20, 20},
{30, 30},
{40, 40},
{50, 50},
{60, 40},
{70, 30},
{80, 20},
{90, 10},
{100, 0}
};

handles = gcnew cli::array<float ^, 2>{
{data[0, 0], data[0, 1]},
{data[1, 0], data[1, 1]}
};

data[0, 0] = float(100);
data[0, 1] = float(100);

MessageBox::Show(handles[0, 0]->ToString());

In this case the message box displays 0 instead of 100...

I've also tried replacing cli::array<float ^, 2> ^handles; with
cli::array<System::Object ^, 2> ^handles; with the same result...
 
B

Ben Voigt [C++ MVP]

I think interior_ptr is a native type so you'd use a normal C++ array
(not
cli::array). You can make .NET arrays of tracking handles of course
(cli::array<T^, 2> where T is a .NET reference type).

Of course, you could store integer indices in the array instead of
interior_ptr.

I've tried using an array of tracking handles like this...

cli::array<float ^, 2> ^handles;
cli::array<float, 2> ^data;

data = gcnew cli::array<float, 2>{
{0, 0},
{10, 10},
{20, 20},
{30, 30},
{40, 40},
{50, 50},
{60, 40},
{70, 30},
{80, 20},
{90, 10},
{100, 0}
};

handles = gcnew cli::array<float ^, 2>{
{data[0, 0], data[0, 1]},
{data[1, 0], data[1, 1]}
};

data[0, 0] = float(100);
data[0, 1] = float(100);

MessageBox::Show(handles[0, 0]->ToString());

In this case the message box displays 0 instead of 100...

I've also tried replacing cli::array<float ^, 2> ^handles; with
cli::array<System::Object ^, 2> ^handles; with the same result...

I said "You can make .NET arrays of tracking handles of course
(cli::array<T^, 2> where T is a .NET reference type)."

The key there is that T must be a reference type. System::Single isn't. As
a result, you get boxing, which means an independent copy.

Actually, only interior_ptr will let you change the array itself.
interior_ptr is a non-fundamental native type, so you can't use it with
cli::array. So either: store indices instead of pointers, or use a native
array of interior_ptr.
 
M

memeticvirus

I've tried using an array of tracking handles like this...
cli::array<float ^, 2> ^handles;
cli::array<float, 2> ^data;
data = gcnew cli::array<float, 2>{
{0, 0},
{10, 10},
{20, 20},
{30, 30},
{40, 40},
{50, 50},
{60, 40},
{70, 30},
{80, 20},
{90, 10},
{100, 0}
};
handles = gcnew cli::array<float ^, 2>{
{data[0, 0], data[0, 1]},
{data[1, 0], data[1, 1]}
};
data[0, 0] = float(100);
data[0, 1] = float(100);
MessageBox::Show(handles[0, 0]->ToString());
In this case the message box displays 0 instead of 100...
I've also tried replacing cli::array<float ^, 2> ^handles; with
cli::array<System::Object ^, 2> ^handles; with the same result...

I said "You can make .NET arrays of tracking handles of course
(cli::array<T^, 2> where T is a .NET reference type)."

The key there is that T must be a reference type. System::Single isn't. As
a result, you get boxing, which means an independent copy.

Actually, only interior_ptr will let you change the array itself.
interior_ptr is a non-fundamental native type, so you can't use it with
cli::array. So either: store indices instead of pointers, or use a native
array of interior_ptr.

"boxing" is the key word. I've been trying to get a grasp on what was
happening here for a couple days now. You're a life saver.

Given my actual problem, compiling a list of references to individual
values in a data set, the "store indices" option is out. It would be
to complex. So, I'm trying to figure how to store a list of type
interior_ptr. I'm having some difficulty getting it to work though.

Could you provide me with an example?
 
M

memeticvirus

I've tried using an array of tracking handles like this...
cli::array<float ^, 2> ^handles;
cli::array<float, 2> ^data;
data = gcnew cli::array<float, 2>{
{0, 0},
{10, 10},
{20, 20},
{30, 30},
{40, 40},
{50, 50},
{60, 40},
{70, 30},
{80, 20},
{90, 10},
{100, 0}
};
handles = gcnew cli::array<float ^, 2>{
{data[0, 0], data[0, 1]},
{data[1, 0], data[1, 1]}
};
data[0, 0] = float(100);
data[0, 1] = float(100);
MessageBox::Show(handles[0, 0]->ToString());
In this case the message box displays 0 instead of 100...
I've also tried replacing cli::array<float ^, 2> ^handles; with
cli::array<System::Object ^, 2> ^handles; with the same result...

I said "You can make .NET arrays of tracking handles of course
(cli::array<T^, 2> where T is a .NET reference type)."

The key there is that T must be a reference type. System::Single isn't. As
a result, you get boxing, which means an independent copy.

Actually, only interior_ptr will let you change the array itself.
interior_ptr is a non-fundamental native type, so you can't use it with
cli::array. So either: store indices instead of pointers, or use a native
array of interior_ptr.

System::Collections::ArrayList ^pointers = gcnew
System::Collections::ArrayList;

pointers->Add(&data[0,0]);

/*
error C2664: 'System::Collections::ArrayList::Add' : cannot convert
parameter 1 from 'cli::interior_ptr<Type>' to 'System::Object ^'
*/
 
B

Ben Voigt [C++ MVP]

I said "You can make .NET arrays of tracking handles of course
(cli::array<T^, 2> where T is a .NET reference type)."

The key there is that T must be a reference type. System::Single isn't.
As
a result, you get boxing, which means an independent copy.

Actually, only interior_ptr will let you change the array itself.
interior_ptr is a non-fundamental native type, so you can't use it with
cli::array. So either: store indices instead of pointers, or use a
native
array of interior_ptr.

System::Collections::ArrayList ^pointers = gcnew
System::Collections::ArrayList;

pointers->Add(&data[0,0]);

/*
error C2664: 'System::Collections::ArrayList::Add' : cannot convert
parameter 1 from 'cli::interior_ptr<Type>' to 'System::Object ^'
*/

A native array of interior_ptr, like perhaps:

std::vector<cli::interior_ptr<float>> pointers;
pointers.push_back(&data[0,0]);
 
M

memeticvirus

System::Collections::ArrayList ^pointers = gcnew
System::Collections::ArrayList;
pointers->Add(&data[0,0]);

/*
error C2664: 'System::Collections::ArrayList::Add' : cannot convert
parameter 1 from 'cli::interior_ptr<Type>' to 'System::Object ^'
*/

A native array of interior_ptr, like perhaps:

std::vector<cli::interior_ptr<float>> pointers;
pointers.push_back(&data[0,0]);

A native array can not contain a managed type (cli::interior_ptr)
 
B

Ben Voigt [C++ MVP]

I said "You can make .NET arrays of tracking handles of course
(cli::array<T^, 2> where T is a .NET reference type)."
The key there is that T must be a reference type. System::Single
isn't.
As
a result, you get boxing, which means an independent copy.
Actually, only interior_ptr will let you change the array itself.
interior_ptr is a non-fundamental native type, so you can't use it
with
cli::array. So either: store indices instead of pointers, or use a
native
array of interior_ptr.
System::Collections::ArrayList ^pointers = gcnew
System::Collections::ArrayList;
pointers->Add(&data[0,0]);

/*
error C2664: 'System::Collections::ArrayList::Add' : cannot convert
parameter 1 from 'cli::interior_ptr<Type>' to 'System::Object ^'
*/

A native array of interior_ptr, like perhaps:

std::vector<cli::interior_ptr<float>> pointers;
pointers.push_back(&data[0,0]);

A native array can not contain a managed type (cli::interior_ptr)

Ahh... the interior_ptr declaration clearly states that this isn't possible.
interior_ptr can only be used as a local variable.

Looks like storing indices is your only option.
 
M

memeticvirus

I said "You can make .NET arrays of tracking handles of course
(cli::array<T^, 2> where T is a .NET reference type)."
The key there is that T must be a reference type. System::Single
isn't.
As
a result, you get boxing, which means an independent copy.
Actually, only interior_ptr will let you change the array itself.
interior_ptr is a non-fundamental native type, so you can't use it
with
cli::array. So either: store indices instead of pointers, or use a
native
array of interior_ptr.
System::Collections::ArrayList ^pointers = gcnew
System::Collections::ArrayList;
pointers->Add(&data[0,0]);
/*
error C2664: 'System::Collections::ArrayList::Add' : cannot convert
parameter 1 from 'cli::interior_ptr<Type>' to 'System::Object ^'
*/
A native array of interior_ptr, like perhaps:
std::vector<cli::interior_ptr<float>> pointers;
pointers.push_back(&data[0,0]);
A native array can not contain a managed type (cli::interior_ptr)

Ahh... the interior_ptr declaration clearly states that this isn't possible.
interior_ptr can only be used as a local variable.

Looks like storing indices is your only option.

The amount of complexity this would introduce into my project is
unreasonable. First of all I'd have to store references to a DataSet
the name of the DataTable, the name of the DataColumn and the index of
the DataRow. And, then what if something changes? Well then I have to
reprocess and redraw everything? The data my program is used to
process is usually incredibly vast and complicated. Consisting of
hundreds of thousands DataRows.

Is garbage collection worth bring a system to it's knees every time
some one changes a digit in a DataGridView or something? This is
stupid!

There has to be a way to create an array of references to the memory
locations of the individual values in the DataSet. I won't accept that
there isn't a better way to do this. I could do it in with 3 lines of
code in standard C++!
 
B

Ben Voigt [C++ MVP]

I said "You can make .NET arrays of tracking handles of course
(cli::array<T^, 2> where T is a .NET reference type)."
The key there is that T must be a reference type. System::Single
isn't.
As
a result, you get boxing, which means an independent copy.
Actually, only interior_ptr will let you change the array itself.
interior_ptr is a non-fundamental native type, so you can't use it
with
cli::array. So either: store indices instead of pointers, or use a
native
array of interior_ptr.
System::Collections::ArrayList ^pointers = gcnew
System::Collections::ArrayList;
pointers->Add(&data[0,0]);

/*
error C2664: 'System::Collections::ArrayList::Add' : cannot convert
parameter 1 from 'cli::interior_ptr<Type>' to 'System::Object ^'
*/
A native array of interior_ptr, like perhaps:
std::vector<cli::interior_ptr<float>> pointers;
pointers.push_back(&data[0,0]);
A native array can not contain a managed type (cli::interior_ptr)

Ahh... the interior_ptr declaration clearly states that this isn't
possible.
interior_ptr can only be used as a local variable.

Looks like storing indices is your only option.

The amount of complexity this would introduce into my project is
unreasonable. First of all I'd have to store references to a DataSet
the name of the DataTable, the name of the DataColumn and the index of
the DataRow. And, then what if something changes? Well then I have to
 
M

memeticvirus

I said "You can make .NET arrays of tracking handles of course
(cli::array<T^, 2> where T is a .NET reference type)."
The key there is that T must be a reference type. System::Single
isn't.
As
a result, you get boxing, which means an independent copy.
Actually, only interior_ptr will let you change the array itself.
interior_ptr is a non-fundamental native type, so you can't use it
with
cli::array. So either: store indices instead of pointers, or use a
native
array of interior_ptr.
System::Collections::ArrayList ^pointers = gcnew
System::Collections::ArrayList;
pointers->Add(&data[0,0]);
/*
error C2664: 'System::Collections::ArrayList::Add' : cannot convert
parameter 1 from 'cli::interior_ptr<Type>' to 'System::Object ^'
*/
A native array of interior_ptr, like perhaps:
std::vector<cli::interior_ptr<float>> pointers;
pointers.push_back(&data[0,0]);
A native array can not contain a managed type (cli::interior_ptr)
Ahh... the interior_ptr declaration clearly states that this isn't
possible.
interior_ptr can only be used as a local variable.
Looks like storing indices is your only option.
The amount of complexity this would introduce into my project is
unreasonable. First of all I'd have to store references to a DataSet
the name of the DataTable, the name of the DataColumn and the index of
the DataRow. And, then what if something changes? Well then I have to

why not store a handle to the array said:
reprocess and redraw everything? The data my program is used to
process is usually incredibly vast and complicated. Consisting of
hundreds of thousands DataRows.
Is garbage collection worth bring a system to it's knees every time
some one changes a digit in a DataGridView or something? This is
stupid!
There has to be a way to create an array of references to the memory
locations of the individual values in the DataSet. I won't accept that
there isn't a better way to do this. I could do it in with 3 lines of
code in standard C++!

Because, the indices change whenever something is inserted or
removed... And, then I'd have to reprocess the data.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top