• Welcome to Valhalla Legends Archive.
 

[C#] Returning multiple value types?

Started by Barumonk, January 15, 2005, 06:59 PM

Previous topic - Next topic

Barumonk

I'm attempting to reproduce this bit of C/C++ code into C#...

#define VectorExpand(v) (v).x, (v).y, (v).z

... and following code is a basic explanation in C# of how it would idealy work...

public class Vector
{
    public float X;
    public float Y;
    public float Z;

    public Vector(float p_X, float p_Y, float p_Z)  //constructor
    {
        X = p_X;
        Y = p_Y;
        Z = p_Z;
    }
}

public class VectorUtil
{
    public void MethodNumber1()
    {
        MethodNumber3( VectorExpand( MethodNumber2() ) );  //this is my problem
    }

    public Vector MethodNumber2()
    {
        return new Vector(43, 56, 83);  //return a vector
    }

    public void MethodNumber3(float p_X, float p_Y, float p_Z)
    { /***/ }
}


VectorExpand returns 3 separate floats that aren't in an array. Well, technically its a params type array, but unless I missed something, its not possible to use params like that.  Does anyone know how to duplicate this in C# or maybe within IL code?  I know its possible in MVC++ but I want to avoid the slowdown from marshalling, im going for speed. =/

MyndFyre

VectorExpand is a macro, not a function, and it doesn't return anything.  Let's say you have the following C function in the same file as VectorExpand:


float calcDistanceFromVector(float x, float y, float z)
{
  return sqrt( pow(x, 2) + pow(y, 2) + pow(z, 2) );
}


Then, you could either:


float doSomething(Vector& rVec)
{
  float dist;
  dist = calcDistanceFromVector(v.x, v.y, v.z);
  return dist;
}


or:


float doSomething(Vector& rVec)
{
  float dist;
  dist = calcDistanceFromVector( VectorExpand(v) );
  return dist;
}

Ultimately, the C Compiler is going to see the exact same code -- the code of the first example.

There is really no reason to use such a macro in C#, and such macros are correspondently not available.
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

Barumonk

The reason is that I don't want to pass a reference type that I don't think qualifies as small enough not to cause a performance hit, and I want to keep backwards compatability with another library.  -_-  Although I just realized that it wouldn't matter with this implementation because I would still be passing the reference type to the function that splits it appart.  I also realize its a macro but they aren't possible in C#, its why im calling it a function because thats the only way I can see it in C#.

Anyway, I just fixed it by changing Vector to a struct instead of a class.

MyndFyre

Quote from: Barumonk on January 15, 2005, 07:53 PM
The reason is that I don't want to pass a reference type that I don't think qualifies as small enough not to cause a performance hit, and I want to keep backwards compatability with another library.  -_-  Although I just realized that it wouldn't matter with this implementation because I would still be passing the reference type to the function that splits it appart.  I also realize its a macro but they aren't possible in C#, its why im calling it a function because thats the only way I can see it in C#.

Anyway, I just fixed it by changing Vector to a struct instead of a class.

If the library function accepts 3 parameters, than your extern statement should contain all three parameters, not one.

If the library function accepts 1 structure parameter, then you should set up your extern functions and structure with the correct interop attributes (MarshalAs, StructLayout, etc).

A macro is not a function in any language.  In this case it is simply a shorthand for accessing the 3 members of a structure.  There is no function in a C library that contains this declaration called VectorExpand.  That macro simply replaces anything within the code with the string:

(v).x, (v).y, (v).z

where (v) is a variable identifier passed into the macro.  The compiler will never, ever, ever see anything called VectorExpand.
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

Barumonk

I know -_-;; I'm saying the closest thing possible in C# to a macro is a function that would have a similar return.  I'm just afraid of boxing and unboxing, or passing oversized objects.  I'll probably just get un-lazy and pass x, y, and z.

MyndFyre

Quote from: Barumonk on January 15, 2005, 08:08 PM
I know -_-;; I'm saying the closest thing possible in C# to a macro is a function that would have a similar return.  I'm just afraid of boxing and unboxing, or passing oversized objects.  I'll probably just get un-lazy and pass x, y, and z.

The only time you have to worry about boxing is:


int n = 5;
object o = n; // can do this, it's boxing!
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.