ref SAFEARRAY(double)

ref SAFEARRAY(double)

Anonymous
Not applicable
750 Views
12 Replies
Message 1 of 13

ref SAFEARRAY(double)

Anonymous
Not applicable
Hello,



I have problem understanding how to pass arrays by ref from C#. I will illustrate using Point.GetPointData for simplicity.



The is working:


Point TestPoint = oApp.TransientGeometry.CreatePoint(0, 0, 0);

System.Array pointCoords1 = new double[3];

TestPoint.GetPointData(ref pointCoords1);



This will not compile because pointCoords2 is unassigned.

System.Array pointCoords2;

TestPoint.GetPointData(ref pointCoords2);



This will not compile either:

double[] pointCoords3;

TestPoint.GetPointData(ref pointCoords3);

TestPoint.GetPointData(ref (pointCoords3 as System.Array));



My questions are:

What is the preferred way of doing this?

Say I want to use SurfaceEvaluator.GetParamAtPoint, how do I know the dimension of the solutionNatures[] parameter?









/Johan

Edited by: JohanLarsson on May 5, 2009 10:48 AM
0 Likes
751 Views
12 Replies
Replies (12)
Message 2 of 13

jeff.pek
Community Manager
Community Manager
Hi Johan -

From a pure C# perspective, this method (and others like it that work with arrays are not optimally defined). For example, they use ref or out when neither is really needed for some parameters, etc.) Let's ignore that as a by-product of the COM interop that's involved.

In general, when working in C# with arrays, you'll need to create an empty array, and then pass that using 'ref' to the method. For example, in this case, I'd bet this will work:

System.Array pointCoords1 = new double[0];
TestPoint.GetPointData(ref pointCoords1);

You need to have assigned pointCoords1 to something (to make C# happy), and you need to use 'ref' to make interop happy. This allows a new array to be created during the call, and reassigned to the reference.

Hope this helps.
Jeff
0 Likes
Message 3 of 13

Anonymous
Not applicable


Hi Jeff,

Thank you for your quick answer, much appreciated.



Why doesnt this work:

double[] pointCoords = new double[0];

TestPoint.GetPointData(ref (pointCoords1 as System.Array));



Bear with me, I'm a noob at C#.



/Johan

0 Likes
Message 4 of 13

jeff.pek
Community Manager
Community Manager
Hi again -

That doesn't work because it's not a System.Array that's wanted; it's a ref to an array of doubles. This is similar, if you're familiar with the concept, of passing a pointer to a pointer, so that you can actually change the underlying array object. If you were to look at the objects involved, you actually get back a different one than you pass in.

Jeff
0 Likes
Message 5 of 13

Anonymous
Not applicable
ugh! Does C# not have a "safe" iterable container such as a std::vector?
0 Likes
Message 6 of 13

jeff.pek
Community Manager
Community Manager
Sure it does. It has several, in fact.
Array itself is easily iterable using foreach().

The trick here is the fact that we need to go through COM to get arrays to/from the Inventor API, which doesn't know anything about .NET's types. The array concept is one that the COM interop layers know how to marshal, so it's relatively straightforward, except for the need to create something that really never has a purpose.

Not quite sure what you're getting at.

Jeff
0 Likes
Message 7 of 13

Anonymous
Not applicable


"get arrays to/from the Inventor API, which doesn't know anything about .NET's types"



ah, thats the catch. I am just used to seeing std C++ like:



typedef std::vector<double> myvector;



void foo(myvector& v)

{

// do something

}



void bar()

{

myvector v; // create the vector



// add some elements



foo(v); // call the function

}





almost totally safe (if std::vector is implemented correctly), pass by reference, clean-ish syntax, no need to "new" anything, also no need to worry about vector length or how to grow/shrink the vector.





"Not quite sure what you're getting at."



I just figured with the new push towards .NET, that the application programmer could use some more sophisticated containers and not have to go so close to the metal. I've never worked with .NET, so I was just surprised to see the "new" and "ref" keywords. Not criticizing, just an observation.

0 Likes
Message 8 of 13

Anonymous
Not applicable
C# intellisense tells me that a System.Array is wanted.

This will not compile.
double[] pointCoords = new double[0];
NominalPoint.GetPointData(ref pointCoords);
0 Likes
Message 9 of 13

jeff.pek
Community Manager
Community Manager
Hi -

The same thing does work for me:

Inventor.Point pt = massProps.CenterOfMass;
// ...
double[] pointData = new double[] { pt_x, pt_y, pt_z };
pt.PutPointData( ref pointData );

double[] pointDataOut = new double[0];
pt.GetPointData(ref pointDataOut);


What error are you getting?

Jeff
0 Likes
Message 10 of 13

Anonymous
Not applicable
I'm using Inventor 2008 & Visual studio 2008.

double[] pointData = new double[] { pt_x, pt_y, pt_z };
Will not compile fo me:
Error 1 The best overloaded method match for 'Inventor.Point.GetPointData(ref System.Array)' has some invalid arguments.
Error 2 Argument '1': cannot convert from 'ref double[]' to 'ref System.Array'


/Johan
0 Likes
Message 11 of 13

jeff.pek
Community Manager
Community Manager
Oh... Inventor 2008...
That uses a different mechanism (imported type library) to define the Inventor API. It must have defined that parameter as a System.Array.

Try using Array.CreateInstance:

Array pointData = Array.CreateInstance(typeof(double), 0);
pt.GetPointData(ref pointData);

- Jeff
0 Likes
Message 12 of 13

jeff.pek
Community Manager
Community Manager
Oh... Inventor 2008...
That uses a different mechanism (imported type library) to define the Inventor API. It must have defined that parameter as a System.Array.

Try using Array.CreateInstance:

Array pointData = Array.CreateInstance(typeof(double), 0);
pt.GetPointData(ref pointData);

- Jeff
0 Likes
Message 13 of 13

Anonymous
Not applicable
Hello
This works fine:
System.Array pointCoords1 = new double[0];

On the ugly side though.
Thanks for your help.
0 Likes