NI TestStand

cancel
Showing results for 
Search instead for 
Did you mean: 

Pass an int64 variable by reference from CVI to Teststand

I tried searching for this problem but couldn’t find a solution. I run test scripts that call a function in C AA_Dat_Get_Statistic( Stats_Record *p_stats ). If I call this function, I sometimes get system level errors (-17001, -17002), TestStand will sometimes crash, and a load of other problems. These errors do not occur until steps after. If I take out this call, TestStand will not crash. There is an obvious problem with this function.

 

I wrote a program in C that calls this function. By bypassing TestStand, I avoid crashes too.

 

Stats_Records contains a few unsigned _int64 variables. The custom struct in TestStand uses another custom struct called Int64. Int64 contains two double variables, High and Low. In short, the variables being passed as a 64 integer are being stored in two 32 double.

 

Does anyone know if passing by reference an int64 will cause these memory crashes? Is this how I should handle this or is there a better way.

 

Thanks in advance. ⨪

0 Kudos
Message 1 of 4
(4,028 Views)

Below is the structure and function:

typedef struct

  {

    unsigned __int64 frame_count;

    double                                   BER;

  }   Stats_Record;

 

AA_Dat_Get_Statistics

                   (int p_card, int p_channel, Stats_Record *p_stats)

  {

    typedef union

      { __int64  int64_BER;

        double   float64_BER;

      }  BER_Union;                  

   

   ....

   BER_Union  BER;

  

    memset (&aa_stats, 0, sizeof(aaSTATS_DATA64));

 

   ....

 

    aa_status = aa_datGet (aa_handle, aa_channel, AA_DATAID_STATISTICS64, &aa_d_ptr);

    p_stats->frame_count           = aa_stats.ullFrameCount;

  

   BER.int64_BER        = aa_stats.floatCumulativeBER;

    p_stats->BER         = BER.float64_BER;

           

    return (status);

 }⨪

 

0 Kudos
Message 2 of 4
(4,026 Views)
I'm not entirely sure what you are doing. You say, "In short, the variables being passed as a 64 integer are being stored in two 32 double", but doubles are 64-bit not 32-bit, perhaps that is why you are seeing a problem. You should be able to put two 32-bit integers in your structure in place of the 64-bit integer and one of the integers will be the high-order bits and the other will be low order bits, however there might still be issues because of structure packing and alignment. Structure packing and alignment are settings which tell the compiler how to add padding to data structures to ensure that data is aligned and sized to optimize speed as microprocessors generally access aligned data faster than unaligned. For example, by default visual studio aligns each data type based on its size to a multiple of that size address and adds padding to the struct as necessary. i.e. 4-byte data types are aligned on 4-byte address values, while 8-byte data types are aligned on 8-byte addresses. Also the entire struct itself is padded on the end as needed to make it a multiple in size of the largest sized data type it contains (up to 8-bytes). Here are some urls explaining this a bit:

http://msdn.microsoft.com/en-us/library/aa296569(VS.60).aspx
http://msdn.microsoft.com/en-us/library/71kf49f1(VS.80).aspx

It really depends on the layout of your structure whether or not this will matter. For example:

struct struct1
{
    char a;
    int b;
    int c;
};

is NOT equivalent to:

struct struct2
{
    char a;
    __int64 b;
};

because in the later case more padding must be added between a and b in order to align b on an 8-byte boundry while in the first case b only needs to be aligned to a 4-byte boundry. Also the entire size of struct2 must be a multiple of 8-bytes as well while struct1 only needs to be a multiple of 4 bytes.

printf("%d %d\n", sizeof(struct1), sizeof(struct2));

You will see that the size of the first struct is 12 bytes while the size of the second struct is 16.

Alternately if you had:

struct struct1
{
    int a;
    int b;
    char c;
};

struct struct2
{
    __int64 a;
    char c;
};

Then 'a' and 'b' in struct1 would line up with 'a' in struct2, however the structs are still not the same size because struct2 must be a mutliple of 8-bytes while struct1 only has to be a multiple of 4-bytes (struct1 is 12 bytes and struct2 is 16 bytes still but this time the padding is at the end instead of between the first two data types).

You could make struct1 the same size as struct2 by padding it with more unused data at the end.

This is all probably more than you wanted to know, but hopefully helps explain things,
-Doug
0 Kudos
Message 3 of 4
(3,995 Views)
In the case of the structure:

typedef struct

  {

    unsigned __int64 frame_count;

    double                                   BER;

  }   Stats_Record;


You can substitute the equivalent structure


typedef struct

  {

    unsigned int frame_count_part1;

    unsigned int frame_count_part2;

    double                                   BER;

  }   Stats_Record;


Because the alignment and structure packing will work out in this case such that the two 32-bit ints in the later structure will line up with the 64-bit integer in the first structure and since both structs are already a multiple of 8-bytes there won't be any padding added onto the end.

-Doug
0 Kudos
Message 4 of 4
(3,993 Views)