LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

DSSetHSzClr - memory size calculation

Solved!
Go to solution
Solution
Accepted by charlie87

You really should first learn a bit more about C pointers before trying such exercises.

 

typedef struct {
	int32_t dimSize[2];
	double Item[1];
	} DataArray;
typedef DataArray **DataArrayPtr;

typedef struct {
	int32_t dimSize;
	LStrHandle String[1];
	} DataStrings;
typedef DataStrings **DataStringsPtr;

typedef struct {
	LStrHandle Name;
	DataArrayPtr Data;
    uint16_t Type;
    DataStringsPtr Strings;
	} Cluster;

typedef struct {
	int32_t dimSize;
	Cluster Variable[1];
	} Buffer;
typedef Buffer **BufferPtr;

 

LStrHandle is a handle itself, as it's name already suggests. As such it only occupies one pointer size in the DataStrings Cluster. So your setVarData() function should more look like this:

 

#if 64Bit
#define uPtr uQ
#else
#define uPtr uL
#else

MgErr setVarString(Cluster* var, ....) { MgErr = err;
int numStrings = .....; // var->Strings = (DataStringsPtr)DSNewHClr(Offset(DataStrings,String) + sizeof(LStrHandle) * numStrings);

// but much better would be to call NumericArrayResize() here, it takes care about reallocating already existing handles or allocating a new one if the handle is currently NULL
err = NumericArrayResize(uPtr, 1, (UHandle*)&(var->Strings), numStrings);
if (err)
return err; for (i = 0; i < numStrings; i++)
{
char *string = .......;
int strSize = strlen(string);
err = NumericArrayResize(uB, 1, (UHandle*)&((*(var->Strings))->String[i]), strSize);
if (err)
return err;
MoveBlock(string, LStrBuf(*(*(var->Strings))->String[i]), strSize);
LStrLen(*(*(var->Strings))->String[i]) = strSize;
}

(*(var->Strings))->dimSize = numStrings;
return noErr;
}

 

Most likely there are some typos in this that won't compile right away, but it gives you an idea what you should do.

 

 

 

Rolf Kalbermatter
My Blog
Message 11 of 14
(759 Views)

I worked it out in a little bit different way, but I think it does the same..

 

int setVarString(Cluster* var, mxArray* mxStr) {
    
     int strSize = mxGetNumberOfElements(mxStr);
     var->Strings = (DataStringsPtr)DSNewHClr(sizeof(DataStrings) + Offset(DataStrings,String));
     if(var->Strings[0] == NULL) // array allocation failed
         return 0;
     
var->Strings[0]->String[0] = (LStrHandle)DSNewHClr(sizeof(uChar)*(strSize+1)); if(var->Strings[0]->String[0] == NULL) // array allocation failed return 0;
// write string to the memory address mxGetString(mxStr, (char*)&((*(var->Strings[0]->String[0]))->str), strSize); //set string size (*(var->Strings[0]->String[0]))->cnt = strSize+1; var->Type = STRING; var->Data = NULL; //set string array size var->Strings[0]->dimSize = 1; return 1 }

Edit: No, it did not the same 😕 ..memory error occured...

0 Kudos
Message 12 of 14
(751 Views)

Your idea works fine. Thank you.

 

I like the solution with ResizeNumericArray you mentioned. I would like to rewrite my code for changing the numeric array (Matrix) in the cluster...

int setVarData(Cluster* var, mxArray* mxdata) {
    int size, row, column;
    row = mxGetM(mxdata);
    column = mxGetN(mxdata);
    size = mxGetNumberOfElements(mxdata);
    var->Type = UNKNOWN;
    
    if( NULL == ((*var).Data = (DataArrayPtr)DSNewHClr(sizeof(DataArray) + Offset(DataArray,Item) + size*sizeof(double))))        
        return 0;
    
    var->Data[0]->dimSize[0] = row;
    var->Data[0]->dimSize[1] = column;
    //memcpy(var->Data[0]->Item, mxGetPr(mxdata), sizeof(double)*size);
    MoveBlock(mxGetPr(mxdata), (*(var->Data))->Item, size * sizeof(double));
    
    if(row == 1 && column == 1)
        var->Type = SCALAR;
    else if((row > 1 && column == 1) || (row == 1 && column > 1))
        var->Type = VECTOR;
    else if(row > 1 && column > 1)
        var->Type = MATRIX;
    else
        var->Type = UNKNOWN;
    
    var->Strings = NULL;
    return 1;
}

 I tryed it in this way but I failed.

   ......

 err = NumericArrayResize(uPtr, 1, (UHandle*)&(var->Data), 1);
        if (err)
            return 0;
 err = NumericArrayResize(fD, 1, (UHandle*)&((*(var->Data))->Item),  size*sizeof(double));
        if (err)
            return 0;

   ......

 

Finally, one more question... when I fill up the Strings Array (or Data Array), I set the var->Data = NULL (or var->Strings = NULL) because the Cluster can represent only either Numeric or only String(s). But lets suppose that at first, the cluster represents Numeric with Numeric Data filled in. Then the cluster type was changed, the Strings data were filled in. Will be the previous Numeric Data deleted automatically when the reference is set to NULL. (var->Data = NULL) or some operation must be performed to free the memory ?

0 Kudos
Message 13 of 14
(740 Views)

@charlie87 wrote:

Finally, one more question... when I fill up the Strings Array (or Data Array), I set the var->Data = NULL (or var->Strings = NULL) because the Cluster can represent only either Numeric or only String(s). But lets suppose that at first, the cluster represents Numeric with Numeric Data filled in. Then the cluster type was changed, the Strings data were filled in. Will be the previous Numeric Data deleted automatically when the reference is set to NULL. (var->Data = NULL) or some operation must be performed to free the memory ?


No! LabVIEW has no automatic garbage collector mechanisme on the low level manager functions. You need to go through the entire array and deallocate each individuel element if it is not NULL. And you need to do that recursively, so also any handles inside a cluster need to be deallocated and if it is an array that contains any handles you need to go in there too and deallocate each and every one through the use of DSDisposeHandle(), obviously after  you went inside it and deallocated everything that it contains.

Rolf Kalbermatter
My Blog
0 Kudos
Message 14 of 14
(735 Views)