Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Using External Code in LabVIEW.pdf
Скачиваний:
49
Добавлен:
29.05.2015
Размер:
1.85 Mб
Скачать

Chapter 5 Advanced Applications

If you read and write a global or static variable or call a non-reentrant function within your CINs, keep the execution of those CINs in a single thread. Even if a CIN is marked reentrant, the CIN functions other than CINRun are called from the user interface thread. For example, CINInit and CINDispose are never called from two different threads at the same time, but CINRun might be running when the user interface thread is calling CINInit, CINAbort, or any of the other functions.

To be reentrant, the CIN must be safe to call CINRun from multiple threads, and safe to call any of the other CIN procedures and CINRun at the same time. Other than CINRun, you do not need to protect any of the CIN procedures from each other, because calls to them are always in one thread.

Code Globals and CIN Data Space Globals

When you declare global or static local data within a CIN code resource, LabVIEW allocates storage for that data. LabVIEW maintains your globals across calls to various routines.

When you allocate a global in a CIN code resource, LabVIEW creates storage for only one instance of it, regardless of whether the VI is reentrant or whether you have multiple references to the same code resource in memory.

In some cases, you might want globals for each reference to the code resource multiplied by the number of usages of the VI (if the VI is reentrant). For each instance of one of these globals, LabVIEW allocates the CIN data space for the use of the CIN. Within the CINInit, CINDispose, CINAbort, and CINRun routines you can call the GetDSStorage routine to retrieve the value of the CIN data space for the current instance. You also can call SetDSStorage to set the value of the CIN data space for this instance.

You can use this storage location to store any 4-byte quantity you want to have for each instance of one of these globals. If you need more than four bytes of global data, store a handle or pointer to a structure containing your globals.

The following code is an example of the exact syntax of these two routines, defined in extcode.h.

int32 GetDSStorage(void);

This routine returns the value of the 4-byte quantity in the CIN data space LabVIEW allocates for each CIN code resource, or for each use

Using External Code in LabVIEW

5-8

www.ni.com

Chapter 5 Advanced Applications

of the surrounding VI (if the VI is reentrant). Call this routine only from CINInit, CINDispose, CINAbort, or CINRun.

int32 SetDSStorage(int32 newVal);

This routine sets the value of the 4-byte quantity in the CIN data space LabVIEW allocates for each CIN use of that code resource, or the uses of the surrounding VI (if the VI is reentrant). It returns the old value of the 4-byte quantity in that CIN data space. Call this routine only from

CINInit, CINDispose, CINAbort, or CINRun.

Examples

The following examples illustrate the differences between code globals and CIN data space globals. In both examples, the CIN takes a number and returns the average of that number and the previous numbers passed to it.

When you write your application, decide whether it is appropriate to use code globals or data space globals. If you use code globals, calling the same code resource from multiple nodes or different reentrant VIs affects the same set of globals. In the code globals averaging example, the result indicates the average of all values passed to the CIN.

If you use CIN data space globals, each CIN calling the same code resource and each VI can have its own set of globals, if the VI is reentrant. In the CIN data space averaging example, the results indicate the average of values passed to a specific node for a specific data space.

If you have only one CIN referencing the code resource, and the VI containing that CIN is not reentrant, choose either method.

Using Code Globals

The following code averages using code globals. The variables are initialized in CINLoad. If the variables are dynamically created (if they are pointers or handles), you can allocate the memory for the pointer or handle in CINLoad and deallocate it in CINUnload. You can do this because CINLoad and CINUnload are called only once, regardless of the number of references to the code resources and the number of data spaces. This example does not use the UseDefaultCINLoad macro, because this .c file has a CINLoad function.

© National Instruments Corporation

5-9

Using External Code in LabVIEW

Chapter 5 Advanced Applications

/*

* CIN source file */

#include "extcode.h"

float64 gTotal; int32 gNumElements;

CIN MgErr CINRun(float64 *new_num, float64 *avg);

CIN MgErr CINRun(float64 *new_num, float64 *avg)

{

gTotal += *new_num; gNumElements++;

*avg = gTotal / gNumElements;

return noErr;

}

CIN MgErr CINLoad(RsrcFile rf)

{

gTotal=0;

gNumElements=0;

return noErr;

}

Using CIN Data Space Globals

The following code averages using CIN data space globals. A handle for the global data is allocated in CINInit, and stored in the CIN data space storage using SetDSStorage. When LabVIEW calls the CINInit,

CINDispose, CINAbort, or CINRun routines, it makes sure

GetDSStorage and SetDSStorage return the 4-byte CIN data space value for that node or CIN data space.

When you want to access that data, use GetDSStorage to retrieve the handle and then dereference the appropriate fields. Finally, use the CINDispose routine you need to dispose of the handle.

/*

* CIN source file */

#include "extcode.h"

typedef struct { float64 total;

int32 numElements;

Using External Code in LabVIEW

5-10

www.ni.com

Chapter 5 Advanced Applications

} dsGlobalStruct;

CIN MgErr CINInit() { dsGlobalStruct **dsGlobals; MgErr err = noErr;

if (!(dsGlobals = (dsGlobalStruct **) DSNewHandle(sizeof(dsGlobalStruct))))

{

/* if 0, ran out of memory */ err = mFullErr;

goto out;

}

(*dsGlobals)–>numElements=0; (*dsGlobals)–>total=0;

SetDSStorage((int32) dsGlobals); out:

return err;

}

CIN MgErr CINDispose()

{

dsGlobalStruct **dsGlobals;

dsGlobals=(dsGlobalStruct **) GetDSStorage();

if (dsGlobals) DSDisposeHandle(dsGlobals);

return noErr;

}

CIN MgErr CINRun(float64 *new_num, float64 *avg);

CIN MgErr CINRun(float64 *new_num, float64 *avg)

{

dsGlobalStruct **dsGlobals;

dsGlobals=(dsGlobalStruct **) GetDSStorage();

if (dsGlobals) { (*dsGlobals)–>total += *new_num; (*dsGlobals)–>numElements++; *avg = (*dsGlobals)–>total / (*dsGlobals)–>numElements;

}

return noErr;

}

© National Instruments Corporation

5-11

Using External Code in LabVIEW

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]