Structures. Part 4. Structures and functions. Passing a structure to a function in the CLR. Returning a structure from a function

Structures. Part 4. Structures and functions. Passing a structure to a function in the CLR. Returning a structure from a function

 


Content
  1. What are the ways of passing a structure to a function?
  2. What are the ways to return a structure from a function?
  3. Example of passing a native structure to a function by value
  4. Example of passing a native-structure to a function by a pointer
  5. How to pass in function a managed-structure which is declared with qualifier ref? Example
  6. How to pass in function a managed-structure which is declared with ‘value’ qualifier? An example
  7. How do I implement a return of a native-structure instance from a function? Example
  8. Example of returning the pointer to a native-structure from function
  9. How return a value-structure instance from a function?
  10. Example of returning a pointer (^) to a value-structure
  11. An example of a return a structure from function that is declared with the ref qualifier

1. What are the ways of passing a structure to a function?

There are 2 ways to pass a native-structure to a function as a parameter:

  • passing the structure by value. With this passing, a copy of the structural variable is made in memory. If the structure is large, then this method is inefficient. The advantage of this method is that all manipulations with a copy of the structure in a function do not affect the original variable;
  • passing a pointer to the structure. In this case, only the pointer to the structure is passed and not the entire structure. If the structure occupies a large amount of memory, such a method provides rapid passing the values of structural variable in function. This is due to the fact that only the pointer to the structure is passed. The disadvantage of this method is that in a function you can accidentally change the values of the original structural variable, in those cases when it is undesirable.

 

2. What are the ways to return a structure from a function?

Just as with the transfer of a structure to a function (see p. 1), there are 2 ways to return:

  • returning the structure by value;
  • returning the pointer to structure.

Advantages and disadvantages of each method are the same as described in paragraph 1.

 

3. Example of passing a native structure to a function by value

Let the “MyStruct.h” module have the native-structure declarations:

// A native structure that describes a point on the coordinate plane
struct MyPoint
{
    int x;
    int y;
};

Let in some class the function EqualPoints(), which compares two points on a coordinate plane is declared. The function returns true if the points are equivalent (equal to each other). Otherwise, the function returns false.

// a function that compares two points
public: bool EqualPoints(MyPoint p1, MyPoint p2)
{
    bool f = false;
    if ((p1.x == p2.x) && (p1.y == p2.y))
        f = true;
    return f;
}

Then the use of the EqualPoints() function can be:

// connecting the module "MyStruct.h"
#include "MyStruct.h"

...

// Passing of a native-structure to a function by value
bool f_equal;
MyPoint pt1, pt2; // p1, p2 – Variables of type "structure"

// Filling in with values
pt1.x = 23;
pt1.y = 35;
pt2.x = 23;
pt2.y = 35;

f_equal = this->EqualPoints(pt1, pt2); // f_equal = true
pt1.x = 100;
f_equal = EqualPoints(pt1, pt2);

 

4. Example of passing a native-structure to a function by a pointer

Let the native-structure be given:

// native-структура
struct MyPoint
{
    int x;
    int y;
};

Below is implemented a function that compares the value of structural variables for equality. The function receives a pointer to a structure.

// Passing a pointer to the MyPoint structure
bool EqualPointsP(MyPoint * p1, MyPoint * p2)
{
    bool f = false;
    if ((p1->x == p2->x) && (p1->y == p2->y))
        f = true;
    return f;
}

The program code that demonstrates the use of the EqualPoints() function.

// Passing the structure using a pointer
MyPoint p1;
MyPoint p2;
bool f_equal;

p1.x = 28;
p1.y = 35;
p2.x = 28;
p2.y = 35;

f_equal = EqualPointsP(&p1, &p2); // f_equal = true
p2.y = 100;
f_equal = EqualPointsP(&p1, &p2); // f_equal = false

 

5. How to pass in function a managed-structure which is declared with qualifier ref? Example

Let the following ref-structure be given.

// ref-structure
ref struct MyPointRef
{
    int x;
    int y;
};

Structures with ref-qualifier are structures of referenced type. For such structures, memory should be allocated using the gcnew utility. Therefore, it is possible to pass a reference to such structures in a function.

Let the function LengthRef() be given, which determines the length of the line that connects 2 points. The function receives two ref-structures as parameters.

// a function that determines the length between two points
float LengthRef(MyPointRef ^p1, MyPointRef ^p2)
{
    float l;
    l = Math::Sqrt((p1->x-p2->x)*(p1->x-p2->x) + (p1->y-p2->y)*(p1->y-p2->y));
    return l;
}

Using the LengthRef() function in some code.

// passing the ref-structure to a function
MyPointRef ^ pt1;
MyPointRef ^ pt2;
float len;

// memory allocation for ref-structures
pt1 = gcnew MyPointRef;
pt2 = gcnew MyPointRef;

// filling ref-structures with values
pt1->x = 35;
pt1->y = 35;
pt2->x = 40;
pt2->y = 40;

len = LengthRef(pt1, pt2); // len = 7.071068

 

6. How to pass in function a managed-structure which is declared with ‘value’ qualifier? An example

A managed structure declared with a ‘value’ qualifier can be passed to the function in one of two ways:

  • by value;
  • using a pointer.

Below are both ways for the value-structure MyPointValue, which has the following declaration.

// value-structure
value struct MyPointValue
{
    int x;
    int y;
};

Way 1.

Let the function LengthValue(), which defines the distance between two points, be given. The function receives two structures of the MyPointValue type as the input parameter. Structures are passed as a parameter-value.

// determination of the distance between two points
float LengthValue(MyPointValue p1, MyPointValue p2)
{
    float len;
    len = (float)Math::Sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
    return len;
}

An example of using the LengthValue() function in another code.

// passing the value-structure
MyPointValue pt1;
MyPointValue pt2;
float len;

pt1.x = 35;
pt1.y = 50;
pt2.x = 40;
pt2.y = 55;
len = LengthValue(pt1, pt2); // len = 7.071068

Way 2. Passing of the structure by pointer.

Let the function LengthValue() be given, which receives two pointers to structures of type MyPointValue.

// function receives a pointer to the value-structure
float LengthValueP(MyPointValue *p1, MyPointValue *p2)
{
    float len;
    len = Math::Sqrt((p1->x-p2->x)*(p1->x-p2->x) + (p1->y-p2->y)*(p1->y-p2->y));
    return len;
}

Using the LengthValue() function in the program.

// passing the value-structure using pointer
MyPointValue pt1;
MyPointValue pt2;
float len;

pt1.x = 0;
pt1.y = 0;
pt2.x = 10;
pt2.y = 10;

len = LengthValueP(&pt1, &pt2); // len = 14.14214

 

7. How do I implement a return of a native-structure instance from a function? Example

You can return a native-structure:

  • by value;
  • using a pointer.

Let the structure MyPoint be given

// native-structure
struct MyPoint
{
    int x;
    int y;
};

Let the program implement the function GetCenterLine(), which calculates the coordinates of the middle of the segment connecting 2 points. The function receives 2 parameters – the coordinates of the ends of the segment.

// Function that returns a native-structure
// The function calculates the coordinates of the middle of the segment
MyPoint GetCenterLine(MyPoint p1, MyPoint p2)
{
    MyPoint res;
    res.x = (p1.x + p2.x)/2;
    res.y = (p1.y + p2.y)/2;
    return res;
}

Demonstration of the return of the native-structure by value.

MyPoint pt1;
MyPoint pt2;
MyPoint res; // result, the memory is allocated

pt1.x = 30;
pt1.y = 20;
pt2.x = 36;
pt2.y = 40;

res = GetCenterLine(pt1, pt2); // res - coordinates of the middle of the segment

 

8. Example of returning the pointer to a native-structure from function

Let the structure MyPoint be given

// native-structure
struct MyPoint
{
    int x;
    int y;
};

Let’s implement the function GetCenterLine(), which gets 2 points and returns a pointer to the structure. In the body of the function, memory allocation for the structure is implemented using the operator new.

MyPoint * GetCenterLine(MyPoint p1, MyPoint p2)
{
    MyPoint * res; // pointer to MyPoint structure

    // allocating memory for the structure
    res = new MyPoint;

    // Calculation of the middle of a segment - filling with values
    resP->x = (p1.x + p2.x)/2;
    resP->y = (p1.y + p2.y)/2;

    return res;
}

Demonstration of work with the function GetCenterLine().

// Return the native structure using the pointer
MyPoint * resPt; // Pointer to the structure - the memory for the structure has not yet been allocated
MyPoint pt1, pt2; // instances of the structure

pt1.x = 28;
pt1.y = 40;
pt2.x = 38;
pt2.y = 50;

// Call the GetCenterLine() function
// for the pointer resPt, memory is allocated inside the function
resPt = GetCenterLine(pt1, pt2);

// test
int d;
d = resPt->x; // d = 33
d = resPt->y; // d = 45

 

9. How to return a value-structure instance from a function?

If a structure with a value qualifier is described in the CLR, then returning an instance of such a structure from the function is no different from the return of the native-structure (see section 7).

 

10. Example of returning a pointer (^) to a value-structure

If a structure is declared with a ‘value’ qualifier, then the function can return a pointer to this structure. Two types of pointers are allowed:

  • A classic pointer, which is denoted by the symbol ‘*’. Returning such pointer from a function is no different from returning a pointer to a native-structure (see p. 8);
  • a pointer designed to work with objects in the CLR. Such pointer is indicated by the symbol ‘^’. The memory for this pointer is allocated by the gcnew utility. The following is an example of a return from a function of such a pointer to a value-structure.

Let the structure with qualifier ‘value’ is declared

// value-structure
value struct MyPointValue
{
    int x;
    int y;
};

Let’s implement the function GetCenterLineVP(), which receives 2 points and returns a pointer to the resulting value-structure. The resulting structure contains the coordinates of the center of the segment that connects the points. The function is as follows:

// Function returns a pointer to the 'value'-structure 
MyPointValue ^ GetCenterLineVP(MyPointValue p1, MyPointValue p2)
{ 
    MyPointValue ^ pv; // Pointer to MyPointValue structure
    pv = gcnew MyPointValue;
    pv->x = (p1.x + p2.x)/2; 
    pv->y = (p1.y + p2.y)/2;
    return pv;
}

Demonstration of a function call from another program code:

// Creating instances of structures with initialization
MyPointValue pt1 = { 20, 30 };
MyPointValue pt2 = { 40, 60 };

// pointer to the structure MyPointValue
MyPointValue ^ resPt;

// calling the function GetCenterLineVP()
// Inside the function, memory for the structure is allocated,
// to which resPt points
resPt = GetCenterLineVP(pt1, pt2);

// test
int d;
d = resPt->x; // d = 30
d = resPt->y; // d = 45

 

11. An example of a return a structure from function that is declared with the ref qualifier

For the structure, which is declared with the qualifier ref has certain features of use. Such structure is a reference type structure. Therefore, the function should return a reference to such a structure (a pointer to the structure). You can not return an instance of the ref-structure (by value) from the function (see paragraph 5).

Let the structure be declared

// ref-structure
ref struct MyPointRef
{
    int x;
    int y;
};

Then the function that gets the 2 points as parameters and finds the center between the two points will be approximately as follows:

// Function that returns a ref-structure
MyPointRef ^ GetCenterLineRef(MyPointRef ^p1, MyPointRef ^p2)
{
    MyPointRef ^resPt;

    // Allocating memory for the resPt pointer
    resPt = gcnew MyPointRef;

    // Filling in the values of the pointer fields
    resPt->x = (p1->x + p2->x)/2;
    resPt->y = (p1->y + p2->y)/2;

    return resPt;
}

Demonstration of the use of the function in another program code.

// pointers to the ref-structure
MyPointRef ^pt1;
MyPointRef ^pt2;
MyPointRef ^resPt;

// memory allocation for pointers pt1, pt2
pt1 = gcnew MyPointRef;
pt2 = gcnew MyPointRef;

// Filling in with values
pt1->x = 20;
pt1->y = 20;
pt2->x = 30;
pt2->y = 40;

// calling the function GetCenterLineRef()
// the memory for the resPt pointer is allocated inside the function
resPt = GetCenterLineRef(pt1, pt2);

// test
int d;
d = resPt->x; // d = 25
d = resPt->y; // d = 30

 


Content