LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Array of doubles filled by DLL contains weird values

Solved!
Go to solution

Hello everyone

 

I am working on a DLL invocation which needs to resize and fill an array of doubles named 'values' (2nd to last parameter). I have defined the signature as follows:

 

 

_declspec (dllexport) uint8_t readDoubleArray(uint8_t handle, LStrHandle lPath, int64_t startTime, 
int64_t endTime, DblArrHdl *values, LongArrHdl *timebase);


Where DblArrHdl is

 

	typedef struct {
int32_t dimSize;
double doubles[1];
} DblArr;
typedef DblArr **DblArrHdl;

 

In the invocation I read doubles from a database, and resize the double array as follows:

 

 


int size = doubleArray.size();

if (NumericArrayResize(0x0A, 1, (UHandle*)values, size) != noErr) {
setLastError(MG_ERR_LABVIEW_ERROR, "Failed to allocate memory");
return FALSE;
}

 I set the size, and copy the values:

 

(**values)->dimSize = size;
for (int i = 0; i < size; i++) {
(**values)->doubles[i] = doubleArray[i];
}

When I use the DbgPrintF to validate the values it gives me a value around 120000 which is correct. However, when returned by labview the array contains strange data, like 5.38564E-315. Here is print out of the 'values' array after it has been through the DLL:

 

 

Here is how I wired it, ignore the clustering, it occurs in the array of values which exits the DLL call.

 

 

I have no idea how this can be. I followed the examples on the site. I also tried the normal DSSetHandleSize, but it didn't change anything. Any idea what I did wrong?


Thanks in advance,

Vincent

Message Edited by DaVince on 10-22-2008 10:10 AM
Download All
0 Kudos
Message 1 of 11
(3,910 Views)

Most likely your OS uses big endian floating points, LabVIEW uses little endian (or the other way around).

To convert those use the following code:

 

 

Ton

Message Edited by TonP on 10-22-2008 07:26 PM
Free Code Capture Tool! Version 2.1.3 with comments, web-upload, back-save and snippets!
Nederlandse LabVIEW user groep www.lvug.nl
My LabVIEW Ideas

LabVIEW, programming like it should be!
Message 2 of 11
(3,890 Views)

I use Visual Studio 2008, on a Windows platform to compile the DLL. As far as I know all DOS machines are little endian. Besides that the first value in the array should not be 0. Even if the endianness would be off, that first element should still have some value.

 

I also have no problems getting parameter values from LabView into the DLL (though I did not use doubles, I did use int32's). But I did try what you said and, the values where different, but still way-off (most values where -4.74341). They also repeat, they should not. The data is sampled and every value should be close to 120.000, but still different.

 

I also have the same problem with the time-stamps. These are 64 bit integers, encoding they time much like LabView except using only first 32bits for seconds, and the 2nd 32bits for the fractions of a second. They also make no sense at all, ranging from 1930 to 2080 or so. The actual data was of 2 days ago. With this also most values are the same. But I want to fix the samples first, becuase they do not have the 64Time to Timestamp conversion step, lowering complexity of the issue.

 

 

It seems to me that they are pointing to a completly different area of memory as to where I wrote the double values.

 

Here is the code where I must have done something wrong:

 

 

Any help is appreciated.
Message Edited by DaVince on 10-23-2008 01:46 AM
0 Kudos
Message 3 of 11
(3,872 Views)

Note that I know the correct value is copied into the (**values)->doubles[i], because after the copying process I did a DbgPrintF("value[0]=%f", (**values)->doubles[0])) and it showed the correct value. Strangly enough I did the same thing with an array of Strings in another function, and it just works... However, the array of strings contains handles instread of doubles.

 

0 Kudos
Message 4 of 11
(3,864 Views)

Well LabVIEW and Windows use different endianess'ess. Does my conversion code work? (or the other way around with the constants switched.

 

Ton

Free Code Capture Tool! Version 2.1.3 with comments, web-upload, back-save and snippets!
Nederlandse LabVIEW user groep www.lvug.nl
My LabVIEW Ideas

LabVIEW, programming like it should be!
0 Kudos
Message 5 of 11
(3,861 Views)

Hi Ton,

 

No unfortunatly your code didn't solve the problem. I tried every combination yielding to either the same double values or the values around -4.7

 

Regards,

Vincent

0 Kudos
Message 6 of 11
(3,854 Views)

I've created a small test project, to see if I could re-create the problem. In this small piece of C++ code I count from 0 to 10 with steps of 0.1, like this:



void countToTen(TD1Hdl *values) {

if (NumericArrayResize(0x0A, 1, (UHandle*)values, 101) != noErr) {
DbgPrintf("Failed to debug");
return;
}
(**values)->dimSize = 101;
for (int i = 0; i <= 100; i++) {
(**values)->elt[i] = 0.1 * i;
}
}

 

 

As you can see from the results:

It makes no sense (should count 0, 0.1, 0.2, 0.3 etc...)

I wired it up like this:

 

Sourcecode of small test project attached. I must be missing something obvious.

 

Regards,

Vincent

Message Edited by DaVince on 10-23-2008 03:07 AM
Download All
0 Kudos
Message 7 of 11
(3,848 Views)
Solution
Accepted by topic author DaVince

Hi again,

 

Vincent, you have problem with alignment. Just add #pragma pack (1) before array declaration:

#pragma pack (1)
typedef struct {
 int32 dimSize;
 float64 elt[1];
 } TD2;
typedef TD2 **TD2Hdl;

and all should be OK.

 

See example in attachment.

 

Andrey. 

 

Message 8 of 11
(3,839 Views)

Hi Andrey!

 

Yes, that was exacty what went wrong. How odd that it goes right with string-handles ...  I could not find this in the documentation (Using External Code in LabView).

 

Regards,

Vincent

 

0 Kudos
Message 9 of 11
(3,828 Views)

You're right, this not directly described...  😉

 

First you should read how LabVIEW stores data in memory,

then read about structure packing pragma,

and finally take a look to C/C++ preprocessor reference,

then you will get feeling how to solve this problem...

Otherwise own DLLs used in LabVIEW code pretty rarely, and Double precision also not very often...

 

The same trouble you may get with clusters, but here behaviour described:

"...The memory layout of a cluster depends on the platform you are running. LabVIEW may add padding between cluster elements so that those elements are aligned to certain address boundaries. Address boundaries relate to the concept of natural alignment. A piece of data is aligned on its natural boundary if the address at which it begins is a multiple of the size of the data. For example, a 4-byte integer is aligned naturally if it begins at an address which is a multiple of four. Most compilers have an upper limit on this boundary at which the restriction is relaxed. For instance, an 8-byte integer may be aligned on a 4-byte boundary. For the platforms on which LabVIEW runs, the alignment constraints are as follows:

  • (Windows) Data is aligned only to 1-byte boundaries.
  • (Mac OS and Linux) Data is aligned naturally up to 4-byte boundaries.
  • (VxWorks PowerPC) Data is aligned naturally up to 8-byte boundaries.

On all platforms, clusters adopt the alignment of their most restrictively aligned element..."

 

best regards and happy wiring...

Andrey.

 

Message Edited by Andrey Dmitriev on 10-23-2008 03:38 PM
0 Kudos
Message 10 of 11
(3,822 Views)