LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

How to read an array of structure(s) from a dll?

Can anybody help me with an example for how to read an array of structure from a DLL (description below) with LabView 8.6? This would allow me to read and display spindle load and speed data.

 

In my understanding the structure I am trying to read contains other two structures that would contain information I need to save. I have included a section o fthe dll function explanations and the code I put together so far. Can anybody enlighten me? I tried all kind of combinations based on the examples / cases I read on this forum. None of them worked and I am stucked...

 

[I do not have much experience with C family of programming languages]

 

Thank you.

 

 

Description

Reads the spindle load meter data and the spindle motor speed data from 1st spindle to the specified spindle number.

In case that "data_num" is bigger than the current spindle number, this function sets the actual read spindle number (the current spindle number) to "data_num" variable after execution. And in case that "data_num" is smaller than the current spindle number, this function reads data for the specified spindle number which is specified by "data_num".

Arguments

FlibHndl   [ in ]

Specify the library handle. See "Library handle" for details.

type   [ in ]

Specify the data type.

0:spindle load meter data
1:spindle motor speed data
-1:all type
data_num   [ in / out ]

Specify the pointer to the number of data to be read. This function returns the number of data which was read actually.

loadmeter   [ out ]

Specify the pointer to the array of ODBSVLOAD structure to store the spindle load meter data and the spindle motor speed data. The number of array must be equal to "*data_num". The ODBSVLOAD structure is as follows.

typedef struct odbspload {
    LOADELM     spload;     /* spindle load meter data */
    LOADELM     spspeed;    /* spindle motor data */
} ODBSPLOAD ;
svload
The LOADELM structure for spindle load meter data
spspeed
The LOADELM structure for spindle motor speed data And the LOADELM structure is as follows.

The LOADELM structure is as follows.

typedef struct loadelm {
    long    data;       /* load meter data, motor speed */
    short   dec;        /* place of decimal point */
    short   unit;       /* unit */
    char    name;       /* spindle name */
    char    suff1;      /* subscript of spindle name 1 */
    char    suff2;      /* subscript of spindle name 2 */
    char    reserve;    /* */
} LOADELM;
data
Load meter data, motor speed data
dec
Place of decimal point
unit
Unit
0:%
1:rpm
name
Spindle name (ASCII)
ASCII code 'S' is stored.
suff1

Subscript of spindle name 1 (ASCII)

  • Series 160/180/210, 160i/180i/210i, 0i, 300i, Power Mate i
    • The spindle number ('1', '2', ...) is stored.

  • Series 150i
    • The value which is defined by parameter (No. 5845, 5846) is stored.

    suff2

    Subscript of spindle name 2 (ASCII)
    When the spindle switching function is available, the following ASCII code is stored.

    In case of main spindle:'1'
    In case of sub spindle:'2'

    When the spindle switching function is not available, NULL('\0') is stored.
    In case of Series 15, data is stored. But it is invalid for the spindle name.

     

    Example

     

     
    The following program reads all spindle load meter, and displays them.
    
    #include "fwlib32.h"
    
    void example( void )
    {
        ODBSPLOAD sp[4];   /* 4 = maximum spinlde number */
        short num = 4;
        short ret = cnc_rdspmeter(h, 0, &num, sp);
    
        if(!ret) {
            int i;
            for(i = 0 ; i < num ; i++) {
                printf("%c%c = %d\n", 
                sp[i].spload.name, sp[i].spload.suff1,
                sp[i].spload.data);
            }
        }
    }
     
    0 Kudos
    Message 1 of 6
    (1,940 Views)

    Hi,

     

     

    Im created an Vi wich enum host on the network. This Vi calls a dll wich fills an array of strucutres.

     

    --header --

     

    typedef struct {
        int32 dimSize;
        uInt8 elt[1];
        } TD3;
    typedef TD3 **TD3Hdl;

    typedef struct {
        uInt32 platform_id;
        TD3Hdl name;
        uInt32 version_major;
        uInt32 version_minor;
        uInt32 type;
        TD3Hdl comment;
        } TD2;

    typedef struct {
        int32 dimSize;
        TD2 elt[1];
        } TD1;
    typedef TD1 **TD1Hdl;

    extern "C" __declspec(dllexport) DWORD  nmServerEnum( const char *server, DWORD server_type,

                                                          const char *domain, TD1Hdl list, DWORD *count);

     

     

    --code--

     

     

     void CopyServerEnum( LPSERVER_INFO_101 &source, TD2 &dest)
    {
        AnsiString temp;

        dest.platform_id = source->sv101_platform_id;

        temp = AnsiString( source->sv101_name );
        strncpy( (*dest.name)->elt, temp.c_str(), (*dest.name)->dimSize );

        dest.version_major = source->sv101_version_major;
        dest.version_minor = source->sv101_version_minor;
        dest.type = source->sv101_type;

        temp = AnsiString( source->sv101_comment );
        strncpy( (*dest.comment)->elt, temp.c_str(), (*dest.comment)->dimSize );
    }


    extern "C" __declspec(dllexport) DWORD  nmServerEnum( const char *server, DWORD server_type, const char *domain, TD1Hdl list, DWORD *count)
    {

        LPSERVER_INFO_101 pBuf = NULL;
        LPSERVER_INFO_101 pTmpBuf;
        DWORD dwLevel = 101;
        DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH;
        DWORD dwEntriesRead = 0;
        DWORD dwTotalEntries = 0;
        DWORD dwTotalCount = 0;
        DWORD dwServerType = server_type;        // all servers
        DWORD dwResumeHandle = 0;
        NET_API_STATUS nStatus;
        PWCHAR pszServerName = NULL;
        PWCHAR pszDomainName = NULL;
        DWORD i;
        AnsiString sDomain, sServer, temp;

        sDomain = AnsiString(domain);
        sServer = AnsiString(server);
        pszServerName = (PWCHAR) malloc(sServer.WideCharBufSize());
        pszDomainName = (PWCHAR) malloc(sDomain.WideCharBufSize());
        if (sServer.Length() > 0)
          sServer.WideChar(pszServerName, sServer.WideCharBufSize());
        else
          pszServerName = NULL;
        if (sDomain.Length() > 0)
          sDomain.WideChar(pszDomainName, sDomain.WideCharBufSize());
        else
          pszDomainName = NULL;
        nStatus = NetServerEnum(pszServerName,  dwLevel, (LPBYTE *) & pBuf, dwPrefMaxLen, &dwEntriesRead,
                                &dwTotalEntries, dwServerType, pszDomainName, &dwResumeHandle);

        // If the call succeeds,
        if ((nStatus == 0) || (nStatus == ERROR_MORE_DATA)) {
            if ((pTmpBuf = pBuf) != NULL) {
                (*list)->dimSize =  min(dwEntriesRead, (*list)->dimSize);
                *count = dwEntriesRead;
                for (i = 0; i < dwEntriesRead; i++) {
                    assert(pTmpBuf != NULL);
                    if (pTmpBuf == NULL) {
                      break; }
                    CopyServerEnum( pTmpBuf, (*list)->elt[i] );
                    pTmpBuf++;
                    dwTotalCount++; }

                if (nStatus == ERROR_MORE_DATA) {
                  return bufferFull;}}
            else {
              return bufferEmpty; } }
        else
           if (pBuf != NULL)
              NetApiBufferFree(pBuf);
        return noErr;
    }

     

     

    The dll has built in Borland C++ 6 and VI in LabVIEW 8.6

     

     

     

    Download All
    0 Kudos
    Message 2 of 6
    (1,918 Views)

    Thank you. This gives me some idea... However, I'm not that good to be able to adapt what you sent to my case. First, in my case I am not sure if the main structure ODBSVLOAD should contain just 1 or 2 of LOADELM structures - one for spload and one for spspeed. Depending on the value of type the data type could be: for 0 : spindle load meter data, for 1: spindle motor speed data, and for -1: all type. So... at first I said I could use just a LOADELM structure in the main structure ODBSVLOAD; and when I set type to 0 I get one type of data, and when I set type to 1 I get the other type. But then the question is what if the type is set to -1, how would I read both types in just one LOADELM structure?...

     

    Based on what you sent it would appear that first I would need to configure the parameter loadmeter to "adapt to type". I would need to initiate an array with the main structure ODBSVLOAD; the following questions arise:

    1. How should the ODBSVLOAD look like: should it have just one LOADELM srtuctures in it or 2 - see above questions raised by type parameter? (in other words, should I have just one cluster in the main cluster or two?)

    2. Should the data in LOADELM structure be represented as a simple numerical indicator or as an array? 

    3. When I initiate the array of structure with ODBSVLOAD, what should I choose for dimension size?

    4. Should I create a counter like you did, even though  counter does not show up anywhere in the DLL function?

    5. All I need is to get the data out for spindle load and spindle motor speed in two different arrays that I can further save in a file.

     

    Any suggestions?

    0 Kudos
    Message 3 of 6
    (1,914 Views)

    Hi

     

    You can configure the input parameter to adapt to type.

    You must initiate the correct structure according to option 0, 1 or -1

    the dll will fill the structure and after you cast the data in your VI.

     

     

    Bruno

    0 Kudos
    Message 4 of 6
    (1,909 Views)

     

    So I guess if the type is 0 or 1 the main structure ODBSVLOAD has just one LOADELM structure in it and if the type is -1, the main structure ODBSVLOAD will have to have 2 LOADELM structures in it?

     

    I thought about it and I'll try it. The other questions still stand.

    0 Kudos
    Message 5 of 6
    (1,907 Views)
    It's not working yet... I hope to be able to post my latest understanding tomorrow. maybe we can discuss on tha one....
    0 Kudos
    Message 6 of 6
    (1,836 Views)