Pass an array as reference 
Author Message
 Pass an array as reference

Hi,

How can I do this in managed C++? I want to create a function, which
takes a String Array as reference. What would the function declaration
look and how would I have to call the function?

Thanks for your answers in advance,
Viktor



Thu, 18 Aug 2005 19:58:24 GMT  
 Pass an array as reference



Quote:
> Hi,

> How can I do this in managed C++? I want to create a function, which
> takes a String Array as reference. What would the function declaration
> look and how would I have to call the function?

> Thanks for your answers in advance,
> Viktor

I haven't found the syntax of what you need yet, but I have a different
approach: use System::Array as the parameter type. The only problem is that
you lose the type information :(

void Function(System::Array ** data)
{
  (*data)->Item[0] = S"Test";

Quote:
}

To use this function do

System::String * strings[] = { S"foo", S"bar"};
System::Array * data = (System::Array*)strings;
Function(&data);

strings[0] will now contain "Test";



Thu, 18 Aug 2005 22:25:09 GMT  
 Pass an array as reference

Quote:

[...]

> I haven't found the syntax of what you need yet, but I have a
different
> approach: use System::Array as the parameter type. The only problem is
that
> you lose the type information :(

> void Function(System::Array ** data)
> {
>   (*data)->Item[0] = S"Test";
> }

> To use this function do

> System::String * strings[] = { S"foo", S"bar"};
> System::Array * data = (System::Array*)strings;
> Function(&data);

> strings[0] will now contain "Test";

Hi Andre

Thanks for your suggestion. There should be a way to do this directly. I
hope someone will help us out with this :-)

Something else: I tried some other function definitions, and they
worked, too. But I have the feeling they're not correct. See yourself:

//Code
//----------------------------------------------------------
// Call of functions:
String* anArray[] = new String*[2];
Function(anArray);

// First alternative:
//-----------------
void Function(String* arrStr[]);

// Second alternative:
//--------------------
void Function([ParamArray] String* arrStr[]);
//_----------------------------------------------------

Both functions work like I want it to work, but I actually don't
understand why. None of them is defined correctly, is it?

Viktor



Fri, 19 Aug 2005 00:29:55 GMT  
 Pass an array as reference
Andre, Viktor,

Quote:
> I haven't found the syntax of what you need yet, but I have a different
> approach: use System::Array as the parameter type. The only problem is
that
> you lose the type information :(

> void Function(System::Array ** data)
> {
>   (*data)->Item[0] = S"Test";
> }

> To use this function do

> System::String * strings[] = { S"foo", S"bar"};
> System::Array * data = (System::Array*)strings;
> Function(&data);

There should be no need to do this. First of all, all managed arrays are
__gc types themselves, and thus, are always passed as references (that is, a
__gc pointer is passed around). So your code above could be rewritten just
as:

void Function(String* data[])
{
  data[0] = S"Test";

Quote:
}

System::String * strings[] = { S"foo", S"bar"};
Function(strings);
Console::WriteLine(strings[0]);

But I'm guessing this was not what Viktor was asking about. I believe he was
asking about passing the array as if it was a C# "ref" argument, so that the
reference itself could be assigned:

void Function2(String* (&data)[])
{
data = new String*[4];
data[0] = S"In a new array Instance!";

Quote:
}

System::String * strings[] = { S"foo", S"bar"};
Function2(strings);
Console::WriteLine(strings[0]);

HTH
--
Tomas Restrepo



Fri, 19 Aug 2005 00:43:36 GMT  
 Pass an array as reference


Quote:
> Hi Andre

> Thanks for your suggestion. There should be a way to do this directly. I
> hope someone will help us out with this :-)

> Something else: I tried some other function definitions, and they
> worked, too. But I have the feeling they're not correct. See yourself:

> //Code
> //----------------------------------------------------------
> // Call of functions:
> String* anArray[] = new String*[2];
> Function(anArray);

> // First alternative:
> //-----------------
> void Function(String* arrStr[]);

IMPORTANT: Actually, an array already *IS* a reference, i.e. this function
will only have a 4byte parameter. So if you simply want to access the arrays
content, this will do. You will only pass a reference to an array (which is
in fact a reference to a reference), if you want to change the array object.

Ex.:

String* arrayA[]  = /**/;
String* arrayB[] = /**/;

SwapArrays(&arrayA, &arrayB);

void SwapArrays(/*reference to array*/ arA, /*reference to array*/ arB)
{
  String * temp[] = *arA;
  *arA = *arB;
  *arB = temp;

Quote:
}

See what I mean?

Quote:

> // Second alternative:
> //--------------------
> void Function([ParamArray] String* arrStr[]);
> //_----------------------------------------------------

This only means, that you can pass an arbitrary number of String*s to the
function, or an array of String*s

Quote:

> Both functions work like I want it to work, but I actually don't
> understand why. None of them is defined correctly, is it?

Depending on what you want to do, they *are* defined correctly.

Quote:
> Viktor

- Andre


Fri, 19 Aug 2005 00:45:13 GMT  
 Pass an array as reference
Viktor,

Quote:
> Something else: I tried some other function definitions, and they
> worked, too. But I have the feeling they're not correct. See yourself:

> //Code
> //----------------------------------------------------------
> // Call of functions:
> String* anArray[] = new String*[2];
> Function(anArray);

> // First alternative:
> //-----------------
> void Function(String* arrStr[]);

This one is perfectly valid. It means that arrStr is of type String*[] (or
actually String __gc* __gc[]), which means "a managed array of __gc pointers
to type System::String".

Quote:

> // Second alternative:
> //--------------------
> void Function([ParamArray] String* arrStr[]);

Valid again, but means a different thing. Arguments marked as ParamArray are
interpreted by languages like C# as if the method took a variable number of
arguments, in this case, a variable number of arguments of type String.

--
Tomas Restrepo



Fri, 19 Aug 2005 00:46:19 GMT  
 Pass an array as reference



[A lot of nice info]

What a coincidence :) I just told Viktor about arrays being references as
well *g*

However, thanks for explaining the syntax of a reference-to-array! Weird
thing, huh?

- Andre



Fri, 19 Aug 2005 00:48:52 GMT  
 Pass an array as reference
Wait a second... shouldn't it be

void Function2(String* (*data)[])
{
*data = new String*[4];
(*data)[0] = S"In a new array Instance!";

Quote:
}

Otherwise the compiler complains that __gc objects can't be passed as
&-references.

- Andre



Fri, 19 Aug 2005 00:54:48 GMT  
 Pass an array as reference
Andre,

Quote:
> Wait a second... shouldn't it be

> void Function2(String* (*data)[])
> {
> *data = new String*[4];
> (*data)[0] = S"In a new array Instance!";
> }

That should work, too.

Quote:

> Otherwise the compiler complains that __gc objects can't be passed as
> &-references.

It's important to remember that as there are both __gc* and __nogc*, there's
also __nogc& and __gc& (which is what we're using here).

I believe the exact error you're refering to is
t.cpp(21) : error C2440: '=' : cannot convert from 'System::String __gc *'
to 'S
ystem::String *'
        Cannot convert a managed type to an unmanaged type

Which just shows a bug in VC++ 7.0 (fixed in VC++ 7.1). This one can be
easily worked around by making the use of a __gc pointer explicitly, like
this:

void Function2(String __gc* (&data)[])
{
data = new String*[4];
data[0] = S"In a new array Instance!";

Quote:
}

--
Tomas Restrepo



Fri, 19 Aug 2005 01:29:43 GMT  
 Pass an array as reference

Quote:

> Andre, Viktor,

[...]

> > System::String * strings[] = { S"foo", S"bar"};
> > System::Array * data = (System::Array*)strings;
> > Function(&data);

> There should be no need to do this. First of all, all managed arrays
are
> __gc types themselves, and thus, are always passed as references (that
is, a
> __gc pointer is passed around). So your code above could be rewritten
just
> as:

> void Function(String* data[])
> {
>   data[0] = S"Test";
> }
> System::String * strings[] = { S"foo", S"bar"};
> Function(strings);
> Console::WriteLine(strings[0]);

> But I'm guessing this was not what Viktor was asking about. I believe
he was
> asking about passing the array as if it was a C# "ref" argument, so
that the
> reference itself could be assigned:

Actually I really only wanted to change the members of the former array.
I knew that an array is a pointer in normal c++ but I thought that in
mc++ you have to define it in another way, because it represents a
pointer to an object.

Quote:
> void Function2(String* (&data)[])
> {
> data = new String*[4];
> data[0] = S"In a new array Instance!";
> }

> System::String * strings[] = { S"foo", S"bar"};
> Function2(strings);
> Console::WriteLine(strings[0]);

Well, thanks to the suggestions of both of you. You really helped me
understand this topic a bit better.

But let me add a question: As (like you say) I'm passing the array
already as a reference, I'm actually really changing the array that has
been passed to the function by his adress. Now, this is a managed array,
and as far as I know there is the risk that the garbage collector will
move the array to an other position in the memory, so the reference
won't be valid, right?

So what would the example look like, if I pin the pointer first?

Thank you very much for your help,
Viktor



Fri, 19 Aug 2005 01:44:11 GMT  
 Pass an array as reference



Quote:
> I believe the exact error you're refering to is
> t.cpp(21) : error C2440: '=' : cannot convert from 'System::String __gc *'
> to 'S
> ystem::String *'
>         Cannot convert a managed type to an unmanaged type

No it's C3602 (seems to be undocumented): I have the german version of
vs.net, but a translation would be something like
error C3603: 'String': A __gc-Typeobject cannot be passed by value.

Quote:

> Which just shows a bug in VC++ 7.0 (fixed in VC++ 7.1). This one can be
> easily worked around by making the use of a __gc pointer explicitly, like
> this:

> void Function2(String __gc* (&data)[])
> {
> data = new String*[4];
> data[0] = S"In a new array Instance!";
> }

This works, thanks! Hehe, this *does* look evil. (The object browser shows a
neat "ref string[]")

- Andre



Fri, 19 Aug 2005 01:45:13 GMT  
 Pass an array as reference



Quote:

> But let me add a question: As (like you say) I'm passing the array
> already as a reference, I'm actually really changing the array that has
> been passed to the function by his adress. Now, this is a managed array,
> and as far as I know there is the risk that the garbage collector will
> move the array to an other position in the memory, so the reference
> won't be valid, right?

> So what would the example look like, if I pin the pointer first?

No pinning is neccessary here. The runtime keeps track of the pointer.
Pinning is only neccessary e.g. if you pass a managed pointer to a native
function.

void SomeNativeFunction(int * p);

__gc class Test
{
public: // evil, I know
   int m_var;

Quote:
}

void main()
{
  Test * p = new Test();

  // p->m_var is located on the heap, as p is located on the heap
  // so we have to pin it, as p my be moved by gc
  // this actually pins the whole object
  int __pin * pinnedInt = p->m_var;

  SomeNativeFunction(pinnedInt);

  // we may unpin the object now, if we continue working with p
  // this will prevent gc from stalling
  // pinnetInt = 0;

Quote:
}

This technique may be used for fast marshalling:

[StructLayout(LayoutKind::Sequential)]
__value struct ManagedValueType
{
   int a, b, c, d;

Quote:
};

__gc class ManagedRefType
{
public:
  ManagedValueType m_data;

Quote:
};

struct UnmanagedStruct
{
  int a, b, c, d;

Quote:
};

void UnmanagedFunction(UnmanagedStruct * p) {/**/}

// the managed app
void main()
{
  ManagedRefType * obj = new ManagedRefType();

  ManagedValueType __pin * pinnedData = obj->m_data;

  UnmanagedFunction(reinterpret_cast<UnmanagedStruct*>(pinnedData));

// unpin
// pinnedData = 0;

Quote:
}

- Andre


Fri, 19 Aug 2005 02:13:49 GMT  
 Pass an array as reference
Hi Viktor,

Quote:
> Actually I really only wanted to change the members of the former array.

Ahh, OK, then do take a look at my other messages :)

Quote:
> But let me add a question: As (like you say) I'm passing the array
> already as a reference, I'm actually really changing the array that has
> been passed to the function by his adress. Now, this is a managed array,
> and as far as I know there is the risk that the garbage collector will
> move the array to an other position in the memory, so the reference
> won't be valid, right?

Not really. In this case, the method receiving the array reference as an
argument has to be managed code itself (whether it is defined in a __gc
class or not is irrelevant). Any managed code will handle __gc pointers (or
references) correctly, and the GC will be aware of what you're doing here,
so you'll be just fine.

You'd only need to pin it down if you needed to create a __nogc pointer to
the first array element so you could pass it to an unmanaged function, which
you're not doing here.

--
Tomas Restrepo



Fri, 19 Aug 2005 03:09:58 GMT  
 Pass an array as reference
Andre, Tomas

I found a page on the net with other interesting information about
Arrays and how to work with them in MC++:

http://www.codeproject.com/managedcpp/csarrays01.asp

Of course, our discussion was much better than this ;-)

Viktor



Fri, 19 Aug 2005 07:12:42 GMT  
 
 [ 14 post ] 

 Relevant Pages 

1. Passing String arrays by reference?

2. how do I pass int array by reference?

3. passing 2d arrays by reference

4. passing 2d arrays by reference

5. Passing multiple arrays by reference

6. Passing array objects by reference

7. passing multi-dimensional array by reference into a function

8. Passing array by reference

9. Passing arrays of srings by reference

10. pass allocated 2d array by reference

11. Trying to pass array of pointers to characters by reference

12. Passing an VB array by reference to a VC Win32 DLL

 

 
Powered by phpBB® Forum Software