The last couple of blog entries I made were on native C++ references and I thought maybe it’s a good time to talk about tracking references in C++/CLI. The punctuator used to specify a tracking reference is % (similar to & for a native reference). See the code snippet below :-
void ChangeString(String^ str)
{
str = "String has been changed";
}
void _tmain()
{
String^ str = "Hello World";
ChangeString(str);
Console::WriteLine(str);
}
The output will show that the function didn’t really change the string the way we intended it to. Now modify the ChangeString function as follows :-
void ChangeString(String^% str)
{
str = "String has been changed";
}
Okay, now it works as expected. For C# folks, this is similar to what happens when you use the ref keyword for function arguments.
I don’t have Whidbey here to test with, but I don’t see why the assignment to
strinChangeString()isn’t reflected inmain. When you writestr="foo"you’re changing the state of the underlyingStringobject, no?[edit] I mean the first version of
ChangeString(), without the%[/edit]Hey Mike
The .NET
Stringobject is immutable. So if you change aString’s underlying string, what happens is that a newStringobject is allocated and assigned to the handle variable. In the first case, because the handle variable is only a copy of the handle variable inmain, the handle variable inmainis not affected. But in the second case the handle variable is the same one as inmainbecause of the%punctuator.ah, ok, it’s a syntactic shortcut that was confusing me. The line in
ChangeString()really means:str = gcnew String("String has been changed");When it’s written without the shortcut, it’s clearer. 🙂
Blew me away until I realised this is just for C++/CLI.
Why would you use this though?
Hi,
I am trying to use a function in a .dll that I have added as a COM reference in VC++, VS2008. In the Object Viewer, it appears as: public virtual void QueryAvailableProperties(string ItemID, out int Count, out int[ ] PropertyIDs, out string[ ] Descriptions, out short[ ] DataTypes). When I hover the mouse above code as I am typing, the tooltip displays: QueryAvailableProperties(String ^ItemID, int % Count, array ^% PropertyIDs, array ^% Descriptions, array ^% DataTypes). The later indicates passing array tracking references but I have not being able produce a solution. The variable Count returns a correct value but an exception Message = “SafeArray cannot be marshaled to this array type because it has either nonzero lower bounds or more than one dimension.” is thrown. An equivalent VC#, VS2008 project returns correct values. Any help would be greatly appreciated.
Regards
Ravith
When I referenced the .dll in VC#, it generated an Interop.xxxxxx.dll and adding that file as a reference in my VC++ project seems to have solved the problem. The function allows me to pass Array^ types instead of the cli:array^ type required originally.