LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Problems creating a Thread Local Variable with a structure

I am unable to get a thread local variable to work with a stucture, any ideas where I am going wrong?
 
 typedef struct {
    char  Flash[100];    //Flash test fault text
    char  Display[100];   //Display test fault text
    char  BackLight[100];   //BackLight test fault text
    char  TouchScreen[100]; //TouchScreen test fault text
    char  Remote[100];   //Remote test fault text
    char  Mic[100];    //Mic test fault text
    char  Adc[100];    //Adc test fault text
    char  Memory[100];   //Memory test fault text
    char  Battery[100];   //Battery test fault text
    char  Bluetooth[100];   //Bluetooth test fault text
    char  GPS[100];    //GPS test fault text
         } F_text;
int FaultText;  //Fault text structure    - handle
 CmtNewThreadLocalVar (sizeof(F_text), NULL, NULL, NULL, &FaultText);
//Inside function
{
 F_code  *F_Code;   //Thread local variable - Fault code structure
   CmtGetThreadLocalVar (FaultText,&F_Text);
   sprintf(F_Text.Flash,"help"); /*gives error :   Left operand of . has incompatible type 'pointer to F_text'.*/

}
 
Thanks
 
Simon
0 Kudos
Message 1 of 10
(4,586 Views)

You have declared a type of structure, but not an instance of it. Maybe you need something like:

    typedef struct {      // Define the 'shape' of an object
        ...
    } structType;

    structType F_text;    // Need to declare an actual object

JR

0 Kudos
Message 2 of 10
(4,584 Views)

thanks for the response,

but I've already tried that and it didn't work.

0 Kudos
Message 3 of 10
(4,574 Views)

You define the TLS struct as a typedef, then refer to your TLS with a pointer of type "pointer to TLS struct".

Like this:

typedef struct ThreadData {
 
  CHAR ErrorString[MAX_STRING_SIZE];
  CHAR StationID[MAX_STRING_SIZE];
 
} ThreadData, * LPTHREADDATA;

DWORD g_dwTlsIndex;   // TLS index declaration as a top level variable

 

// ===========  Code ============

LPTHREADDATA lpThreadData = TlsGetValue (g_dwTlsIndex);   // Get pointer to TLS as thread data struct.  

// Could make it clearer with a cast I suppose ... TlsGetValue return is of type "pointer to void" that you need to cast / coerce to some other type to use.

LPTHREADDATA lpThreadData = (LPTHREADDATA) TlsGetValue (g_dwTlsIndex);
 
 strcpy (lpThreadData->StationID, "None");     // and copy a string into it

 

So you can see, there never is a declaration of the struct, it is just a way of considering the layout of the TLS.  I'm not sure just what's happening with the NI stuff, I just code the use of the TLS directly per the Win32 API.

 

Menchar

 

 

0 Kudos
Message 4 of 10
(4,573 Views)
And I should have shown how I set up the TLS:
 
// Allocate a TLS index.
 
if ((g_dwTlsIndex = TlsAlloc ()) == 0xFFFFFFFF) return FALSE;
 
// allocate thread storage area off the heap and set pointer to it in TLS
 
lpThreadData = (LPTHREADDATA) calloc (1, sizeof (ThreadData)); 
if (lpThreadData != NULL) fIgnore = TlsSetValue (g_dwTlsIndex, lpThreadData);
 
and how to tear it down ...
 
// Free the allocated memory for this thread.
 
lpThreadData = TlsGetValue (g_dwTlsIndex); 
if (lpThreadData != NULL) free (lpThreadData);
 
// Release the TLS index.
TlsFree (g_dwTlsIndex);
   
0 Kudos
Message 5 of 10
(4,560 Views)
Hello big_h_no1,

Are you sure you didn't have a case mismatch when you tried JR's suggestion? I noticed that you named your type F_text, but you are using F_Text in the call to CmtGetThreadLocalVar.

In any case, I tried the following code, and it compiled okay:

typedef struct {
    char  Flash[100];    //Flash test fault text
    char  Display[100];   //Display test fault text
    char  BackLight[100];   //BackLight test fault text
    char  TouchScreen[100]; //TouchScreen test fault text
    char  Remote[100];   //Remote test fault text
    char  Mic[100];    //Mic test fault text
    char  Adc[100];    //Adc test fault text
    char  Memory[100];   //Memory test fault text
    char  Battery[100];   //Battery test fault text
    char  Bluetooth[100];   //Bluetooth test fault text
    char  GPS[100];    //GPS test fault text
} F_text;

int main (int argc, char *argv[])
{
    F_text    myVar;
    int          FaultText;  //Fault text structure    - handle

    CmtNewThreadLocalVar (sizeof (F_text), NULL, NULL, NULL, &FaultText);
    CmtGetThreadLocalVar (FaultText ,&myVar);

    return 0;
}

0 Kudos
Message 6 of 10
(4,556 Views)

Thankyou everybody,

Luis_G I agree your example does compile and does work within the main.  I am calling the thread local variable from multiple functions and the above example only sets the data locally (see below example).

I find it odd that you cannot delare a pointer as you can with and int as per the ni example.

#include <cvirte.h>
void test(void);
void function(void);
typedef struct {
    char  Flash[100];    //Flash test fault text
          } textstruct;
int FaultText;  //Fault text structure    - handle
int main (int argc, char *argv[])
{
 if (InitCVIRTE (0, argv, 0) == 0)
  return -1;    /* out of memory */


 CmtNewThreadLocalVar (sizeof(textstruct), NULL, NULL, NULL, &FaultText);


 test();
 return 0;
}

void test(void)
{
 textstruct  threadtext;   //Thread local variable
   CmtGetThreadLocalVar (FaultText,&threadtext);
   function();
   MessagePopup ("threadtext", threadtext.Flash);
   
}
void function (void)
{
 textstruct  threadtext;   //Thread local variable
   CmtGetThreadLocalVar (FaultText,&threadtext);
   sprintf(threadtext.Flash,"help");
}

 
0 Kudos
Message 7 of 10
(4,541 Views)

I think I have cracked it (see below).

#include <utility.h>
#include <userint.h>
#include <ansi_c.h>
#include <cvirte.h>
void test(void);
void function(void);

typedef struct {
    char  Flash[100];    //Flash test fault text
          } textstruct, *pointstruct;

int FaultText;  //Fault text structure    - handle

int main (int argc, char *argv[])
{
 if (InitCVIRTE (0, argv, 0) == 0)
  return -1;    /* out of memory */


 CmtNewThreadLocalVar (sizeof(textstruct), NULL, NULL, NULL, &FaultText);


 test();
 return 0;
}

void test(void)
{
 pointstruct ptr;
 CmtGetThreadLocalVar (FaultText,&ptr);
   function();
   MessagePopup ("test", ptr->Flash);
   
}
void function (void)
{
 pointstruct ptr;
 CmtGetThreadLocalVar (FaultText,&ptr);
   sprintf(ptr->Flash,"help");
   MessagePopup ("function", ptr->Flash);
}

0 Kudos
Message 8 of 10
(4,540 Views)
Yes, you're right. Your last code snippet is correct.

I should have pointed out that while the initial code compiled okay, it wasn't actually correct. You need to pass the address of a pointer to CmtGetThreadLocalVar, not the pointer itself. I had been assuming that the problem you were having was that you were getting compile errors, and so I just did a quick copy/paste to make sure that it compiled, but I didn't look at it very carefully. Sorry about that.

Luis

0 Kudos
Message 9 of 10
(4,522 Views)

Thanks for all the help

 

Simon

0 Kudos
Message 10 of 10
(4,486 Views)