ni.com is currently undergoing scheduled maintenance.

Some services may be unavailable at this time. Please contact us for help or try again later.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Calling LabVIEW DLL from C with 2d array strings

I am trying to write a DLL in C that calls a LabVIEW DLL that has a number of functions that each return a 2D array of strings which are the formatted measurements, with column 1 being the measurement name and column 2 being the measurement. I wanted to use the 2D array of strings since this would give a uniform interface for returning measurements. Ive cobbled together bits and pieces of messages and example code I've found here into something that almost works, and was hoping someone with a little more experience in interfacing C with LabVIEW DLLs would be able to help me.

Here's a little snippet from the header file generated when building the LabVIEW DLL:

typedef struct {
    long dimSizes[2];
    LStrHandle String[1];
} TD1;

typedef TD1 **TD1Hdl;

long __cdecl TestVI(char serialNumber[],  TD1Hdl *formattedMeasurements, char ErrorDescription[], long len);
The "TestVI" VI generates a 2D array of strings. The cell contents and number of rows are random to simulate different measurement names and measurements.

Here's a snippet for the wrapper class:
class CArgoTestsLabVIEW  
{
   public:
      CArgoTestsLabVIEW();
      virtual ~CArgoTestsLabVIEW();

      // test modules called from parent DLL
      BOOL GetResult_LV(CString resultName, double *result);
      long TestVI_LV(CString serialNumber);
   
   private:
      TD1Hdl m_LVStringArray;
      CMapStringToString   m_resultMap;
      
      InitMeasurementsArray();
      PopulateResultMap();
}

The "m_LVStringArray" is intended to hold the 2D array of strings that the test modules spit out. The "m_resultMap" is just for accessing the measurements from the parent DLL via the "GetResult_LV" function.

The implementation of TestVI_LV is:
long CArgoTestsLabVIEW::TestVI_LV(CString serialNumber)
{
    long rc = 0;
    char errStr[BUFFERLEN];

    strcpy(errStr,"");

    rc = InitMeasurementsArray();

    if (rc == 0) {
        rc = TestVI(serialNumber.GetBuffer(serialNumber.GetLength()), &m_LVStringArray, errStr, BUFFERLEN);
        PopulateResultMap();
    }
    return rc;
}
The accessor functions InitMeasurementsArray and PopulateResultMap are:
long CArgoTestsLabVIEW::InitMeasurementsArray()
{
	MgErr err;

	if (m_LVStringArray)
	{
		DSDisposeHandle(m_LVStringArray);
	}
	m_LVStringArray = (TD1Hdl)DSNewHandle(sizeof(TD1));
        // code to check for NULL

	// Set number of strings in array to 0
	(*m_LVStringArray)->dimSizes[0] = 0;
	(*m_LVStringArray)->dimSizes[1] = 0;
		
	// Set total size of array structure. For now it is only as big as the long variable.
	err = DSSetHandleSize((UHandle)m_LVStringArray, sizeof(long));
	// code to check for error 

	return 0;
}

void CArgoTestsLabVIEW::PopulateResultMap()
{
	int	numberOfResults;
	int i;
	int charCnt;

	numberOfResults = (*m_LVStringArray)->dimSizes[0];

	if (numberOfResults == 0) {
		return;
	}

	m_resultMap.RemoveAll();

	for (i = 0; i < numberOfResults; i++) {
		charCnt = (*((*m_LVStringArray)->String[i * 2]))->cnt;
		(*((*m_LVStringArray)->String[i * 2]))->str[charCnt] = '\0';
		charCnt = (*((*m_LVStringArray)->String[i * 2 + 1]))->cnt;
		(*((*m_LVStringArray)->String[i * 2 + 1]))->str[charCnt] = '\0';

		m_resultMap.SetAt((LPCTSTR)  (*((*m_LVStringArray)->String[i * 2]))->str, (LPCTSTR)  (*((*m_LVStringArray)->String[i * 2 + 1]))->str);
	}
}
The problem I have is that I eventually get an access violation from the run-time engine if I try to call the test VI in a loop. I'm obviously having a memory management problem, but it escapes me as to where the problem is. Anybody have any ideas?
0 Kudos
Message 1 of 2
(3,208 Views)


smercurio_fc wrote:

The problem I have is that I eventually get an access violation from the run-time engine if I try to call the test VI in a loop. I'm obviously having a memory management problem, but it escapes me as to where the problem is. Anybody have any ideas?

...
(*((*m_LVStringArray)->String[i * 2]))->str[charCnt] = '\0';

Hi smercurio,
      Have you solved this?  I don't work with C much anymore, but it looks, here, as if the memory at str[charCnt] isn't yours to address/change.
Is index "charCnt" one char past the end of the String-memory allocated by LabVIEW? 

 
just an idea! Smiley Happy
 
Hmmm, maybe page 9 is a bit far back to fish in the unanswered posts. Smiley Tongue

Message Edited by Dynamik on 03-03-2006 02:03 AM

When they give imbeciles handicap-parking, I won't have so far to walk!
0 Kudos
Message 2 of 2
(3,131 Views)