|
Right, that's just making use of the pointer semantics of interior pointers.
My main point of confusion right now is that my initial understanding was that handles could only point to whole CLI objects (ie not interior data members no matter their type). In which case that would be an important place where interior pointers would need to be used. However, I can make a ref class Foo with a data member of a ref class Bar and a data member of a managed value class V (each of those classes as int data members) and use a handle to point to the Bar member, the V member, or even the int members of those 2 objects. So while using a handle to the int might incur a boxing cost, its still quite possible. So the only thing I see handles unable to point which interior pointers can are native objects. This seems to say that interior pointers are only useful for when pointer semantics are required or you need them for interop which I thought for sure was not the only time you needed them.
That's a little confusing considering:
"CLI object references always refer to a whole object of CLI type on the CLI heap (e.g., it cannot refer to a directly held member inside a CLI reference type object, or to an object on the C++ heap)."
from page 27 of the C++/CLI Design Rationale. http://www.gotw.ca/publications/C++CLIRationale.pdf
|
|
|
|
|
Adding to led mikes comment, the tracking handle points to a managed object's header. It is a whole-object pointer. The interior pointer points to a manage object's data and you can use a pointer-typed interface to move from one data item to another. So, interior pointers only are used in special situations.
"We make a living by what we get, we make a life by what we give." --Winston Churchill
|
|
|
|
|
Ok, so for the most part an interior pointer and handle can point to the same types of things (i.e., a ref class, a ref class data member of another ref class, a value type data member of a ref class, etc). The difference is that when they are seemingly pointing at the same thing, the handle is pointing at the object's header information (and thus the whole object) while the interior pointer has the specific address of the object's data itself (which is what allows it to use pointer semantics). That makes sense I think. But you say interior pointers are only used in special situations. That seems to imply that replacing handles with interior pointers in some situations is not going to work (which I didn't think was the case). Is that right? And if so, could you give me a basic example of such a situation?
I'm still unclear on the implications of the quote from the Design Rationale doc. When it says handles can't point to interior data members of an object, that just means it can't point to the specific address of the data giving it pointer semantics? But it can still point to the whole object data member meaning they're perfectly useful for pointing to interior data members as long as you don't need pointer semantics and just want a tracking pointer. No?
|
|
|
|
|
using namespace System;
void MultiplyArray( array<int>^ data, int value )
{
// Interior pointers only refer to the managed object's state or data.
// They are initialized with an address of a managed object's data item.
// They do not produce verifiable code; so, you cannot compile this code
// with /clr:safe. They cannot be converted to or casted to a native pointer.
// However, interior pointers can be converted to pinned pointers.
interior_ptr<int> begin = &(data[0]);
interior_ptr<int> end = begin + data->Length;
while (begin < end )
{
*begin *= value;
++begin;
}
}
// Tracking references point to the whole managed object.
// Using a tracking reference here does not make much sense since using a
// tracking handle has the same affect in this case.
void PrintArray( array<int>^% vals )
{
for each (int val in vals)
{
Console::WriteLine(val);
}
}
int main(array<System::String ^> ^args)
{
// Tracking handles refer to the whole managed object.
// They can be initialized with gcnew.
array<int>^ values = { 1, 2, 3, 4, 5 };
MultiplyArray(values, 2);
PrintArray(values);
return 0;
}
|
|
|
|
|
Ok, thanks, that's a good example of where interior pointers can simplify things. But you could do similarly with just handles if you have an array of 'handle to typeX' even if its not quite as nice a solution.
(Sorry I'm not sure how to use the code tag and ignore HTML so the array type is shown.)
#include "stdafx.h"
using namespace System;
// Can multiply the array elements when the array type is handle to type
// rather than needing interior pointers.
// A little silly with int due to boxing costs but imagine with an array of
// ref class objects where you do perform some useful change to each element
void MulArray( array<int^>^ data, int value )
{
for each(int^% i in data)
{
*i *= value;
}
}
// Tracking references point to the whole managed object.
// Using a tracking reference here does not make much sense since using a
// tracking handle has the same affect in this case.
void PrintArray( array<int^>^ vals )
{
for each (int val in vals)
{
Console::WriteLine(val);
}
}
int main(array<System::String ^> ^args)
{
// Tracking handles refer to the whole managed object.
// They can be initialized with gcnew.
array<int^>^ values = { 1, 2, 3, 4, 5 };
MulArray(values, 2);
PrintArray(values);
return 0;
}
Now I understand why you'd want your version in some cases where you're being passed an array<int>^ that you didn't choose to create. In theory you could create a new array (of array<int^>^) to copy the array<int>^ to use with my version if you wanted to avoid interior pointers and make the code verifiable. I'm just trying to draw a solid line in my mind dividing the uses of handles and interior pointers. Like I said (and you just showed), they can be useful for pointer semantics. But you can still find a way to avoid them and use handles to point to interior members. So are the only time they're absolutely necessary are when you must have pointer semantics and in some interop scenarios (where native pointers can convert implicitly to interior pointers but not handles)? They can simplify some situations where you're pointing to interior members of a ref class but you can still get around doing so via handles (even if it may not be as elegant and performant as the interior pointer solution).
|
|
|
|
|
What is the correct syntax for setting up a DataSet array in managed C++
In C# I used the following
public static DataSetPI40[][] dsPI40 = new DataSetPI40[8][];
and I tried the following in C++ but had errors.
public:
static DataSetPI40[8][40]^ dsPI40 = gcnew DataSetPI40[8][40];
Can someone please help with this, thanks.
Michael
|
|
|
|
|
Arrays are different in C++/CLI:
array<DataSetPI40^, 2>^ dsPI40 = gcnew array<DataSetPI40^>(8, 40);
"We make a living by what we get, we make a life by what we give." --Winston Churchill
|
|
|
|
|
I still get the following error.
Error 6 error C2767: managed array dimension mismatch :
expected 1 argument(s) - 2 provided
After I change this to the following and it worked.
after adding ", 2" to the otherside it worked
But when I add the second dimension as follows it compiles.
static DataSetPI40::PIVar40DataTable^ PIVar40 =
gcnew DataSet_PI40::PIVar40DataTable();
but, when I refer to the Dataset I get the following error.
dsPI40[1][5]->PIVar40[nRecNumID]->ColumnName
Error 8 error C3262: invalid array indexing: 1 dimension(s) specified for 2-dimensional 'cli::array<Type,dimension> ^'
Michael
|
|
|
|
|
I am sorry about not including the second "2":
<code>array<DataSetPI40^, 2>^ dsPI40 = gcnew array<DataSetPI40^, 2>(8, 40);
dsPI40[1, 5]->PIVar40[nRecNumID]->ColumnName</code>
"We make a living by what we get, we make a life by what we give." --Winston Churchill
|
|
|
|
|
Thanks, but I understood that. However, when I add the variable for the table as above it compiles also.
When I try to load the table above with data it says there is only one dimension, therefore I must be stating the table variable incorrectly I assume, do you know what the problem is.
Michael
|
|
|
|
|
You didn't look at my above response carefully! You wrote:
dsPI40[1][5]->PIVar40[nRecNumID]->ColumnName
I responded with:
dsPI40[1, 5]->PIVar40[nRecNumID]->ColumnName
Your code above had "[1][5]" where the complier compiled only up to the "]" after the 1 and believe you only supplied one dimension.
"We make a living by what we get, we make a life by what we give." --Winston Churchill
|
|
|
|
|
Everything works great, thanks for the help.
Michael
|
|
|
|
|
I want display only the seconds/milliseconds.
How to code that one, it seems my code below is not working. result is always 0;
System::DateTime moment = System::DateTime(11);
int millisecond = moment.Millisecond;
******************************
I just want to
know everything
|
|
|
|
|
AFAIK the constructor accepts a number of ticks (1/10 of a microsecond), so your
moment is almost zero.
|
|
|
|
|
Luc Pattyn wrote: AFAIK the constructor accepts a number of ticks (1/10 of a microsecond), so your
moment is almost zero.
And how do you "know" that? You haven't been reading the documentation have you?
Can't you get in trouble for that?
|
|
|
|
|
I plead guilty; I am known to occasionally read the documentation.
Sometimes I even believe that helps me in understanding what is going on and why.
|
|
|
|
|
Thanks to all. I got it. :->
******************************
I just want to
know everything
|
|
|
|
|
Bros,
How to code the network speed detection?
What i mean is i want to detect the upload and download using clickbutton. When I press a button it will show to textbox1 the upload speed and textbox2 the download speed.
example:
TextBox1 = 42 kbps
TextBox = 54 kbps
Is anybody here how to do that? Much better if you can give me some links for basic.
Thanks in advance.
******************************
I just want to
know everything
|
|
|
|
|
I doubt there is a way to simply find this as there isn't really a fixed upload and download speed, as the server at the other end is a factor of the upload and download speed.. You could get the application to, for example, download a file and work out the speed in kbps from that, and do the same but upload a file..? This would give an estimation to the upload and download speed..
Hope this helps!
--PerspX
|
|
|
|
|
Hello,
I need to retrieve ALL subdirectories under a specified directroy in my C++ program. Could anyone please tell me how to do this.
Thanks
cy163
|
|
|
|
|
You can with one of the overloads of Directory::GetDirectories
specify AllDirectories if you want it to work recursively,
(or organize a recursion yourself if you are still on .NET 1.x)
|
|
|
|
|
When I have the following code
String ^sBuffer;<br />
sBuffer->Format("Target number is {0}", this->id);
sBuffer will not be updated, but if I change it to
String ^sBuffer;<br />
sBuffer= String::Format("Target number is {0}", this->id);
It seems to work well. However, Is this the best way to use Format?
Programmer
Glenn Earl Graham
Austin, TX
|
|
|
|
|
strings are immutable. What you're doing is as good as anything.
Christian Graus - Microsoft MVP - C++
"I am working on a project that will convert a FORTRAN code to corresponding C++ code.I am not aware of FORTRAN syntax" ( spotted in the C++/CLI forum )
|
|
|
|
|
I know same classes that I had to use with Visual c++ 6.0
How can I Insert those classes in my new project Visual C++ NET 2005 ?
|
|
|
|
|
1. You can just copy the .h/.cpp files in to the project folder.
2. Right click on the Project in the Solution Explorer and selecct Add->Existing Items
3. Select all the .h / .cpp files from the open file dialog
4. It will add your existing classes into the project
If you want to add the files from the different folder than your project folder, make sure you set the include path correctly.
Regards,
Sivakumar R
|
|
|
|