10-22-2008 10:03 AM - edited 10-22-2008 10:10 AM
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
Solved! Go to Solution.
10-22-2008 12:25 PM - edited 10-22-2008 12:26 PM
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
10-23-2008 01:40 AM - edited 10-23-2008 01:46 AM
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:
10-23-2008 01:55 AM
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.
10-23-2008 02:03 AM
Well LabVIEW and Windows use different endianess'ess. Does my conversion code work? (or the other way around with the constants switched.
Ton
10-23-2008 02:31 AM
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
10-23-2008 03:06 AM - edited 10-23-2008 03:07 AM
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
10-23-2008 07:12 AM
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.
10-23-2008 08:07 AM
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
10-23-2008 08:36 AM - edited 10-23-2008 08:38 AM
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:
On all platforms, clusters adopt the alignment of their most restrictively aligned element..."
best regards and happy wiring...
Andrey.