-1

i am doing new study about LabVIEW and DLL. I created a DLL which built by LabVIEW.

This is a header file.

#include "extcode.h"
#pragma pack(push)
#pragma pack(1)

#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
    int32_t numeric_input;
    LStrHandle string_input;
} Cluster;

/*!
 * Cluster_dll
 */
void __cdecl Cluster_dll(Cluster *Input, int32_t *numeric_output, 
    char string_output[], int32_t length);

MgErr __cdecl LVDLLStatus(char *errStr, int errStrLen, void *module);

#ifdef __cplusplus
} // extern "C"
#endif

#pragma pack(pop)

To call it, i created Visual C++ program.

#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <cstdint> 
#include "C:\Program Files\National Instruments\LabVIEW 2014\cintools\extcode.h"
using namespace std;

struct Input_t{
    int32_t A;
    LStrHandle B;
} variable_t;

typedef void (*FUNC)(Input_t,int32_t *,char [],int32_t);


int _tmain(int argc, _TCHAR* argv[])
{
    HINSTANCE hDLL = LoadLibrary(TEXT("C:\\Cluster_dll.dll"));
        if(hDLL == NULL){
        cout << "error" << endl; // error check
    }


    FARPROC lpIO = GetProcAddress(HMODULE(hDLL),"Cluster_dll");

    //define type
    FUNC myFunc;
    myFunc = FUNC(lpIO);

    //define returned variable

    Input_t Cluster;
    Cluster.A = 1;
    Cluster.B;

    int32_t myValue = 0;
    char str[10];

    //call function
    myFunc(Cluster,&myValue,str,10);


    FreeLibrary(hDLL);
    return 0;
}

i built it and ran. then the application crashed. i guess i cannot treat "LStrHandle" correctly. it is an original data type defined by LabVIEW.

typedef struct { 
    int32 cnt;  /* number of bytes that follow */ 
    uChar str[1];  /* cnt bytes */ 
} LStr, *LStrPtr, **LStrHandle; 

I looked for NI web page and some web resource but could not solve the crash.

Please comment if you have any advice.

CharlesB
  • 86,532
  • 28
  • 194
  • 218
labRubys
  • 21
  • 1
  • 7

1 Answers1

1
  1. if you are not using the generated header, at least insert #pragma pack(1)
  2. Your generated function accepts a pointer to Cluster, however you redefine it as the one accepting the cluster itself. This is a mistake. Likely correction:

    typedef void (*FUNC)(Input_t*,int32_t *,char [],int32_t);
    
  3. All internal LabVIEW data handles are allocated on the heap with LabVIEW memory manager functions. I.e. you can not allocate Input_t Cluster on a stack and pass it to a LabVIEW generated function.

You have to use something like that:

Input_t *Cluster(DSNewPtr(sizeof(Input_t));
Cluster->A = 1;
Cluster->B = DSNewHandle(sizeof(LStr));

you should also program your logic to check for memory allocation errors and proper deallocations

CharlesB
  • 86,532
  • 28
  • 194
  • 218
mzu
  • 723
  • 3
  • 13