09-26-2013 08:02 AM
Hello,
I try to call this function in a CLFN:
DLLIMPORT int ReadDataFromConfig(
unsigned int devID,
unsigned int offset,
unsigned char *output,
unsigned int length
)
When creating the VIs from the Import Shared Library tool this function prototype in labview is:
int32_t ReadDataFromConfig(uint32_t devID, uint32_t offset, CStr output, uint32_t length);
The problem is that when I call the function, the returned values are not what I'm expecting.
The function should return a table of characters sized by the input parameter length.
Should I pass an U8 table sized by length instead of the CStr Output ?
Thanks
09-26-2013 10:25 AM
Hi
The C-function is expecting a pointer to a memory area of size "length".
Setting up the LV interface it should be possible to get a string in that place.
Gabi
Do you have an example of your code ?
09-26-2013 10:35 AM
Can you show your LabVIEW code? Do you have any documentation for this function?
You need to pass an initialized string of the appropriate length into the CLFN for the string (unsigned char *) output. Alternatively you can pass in an initialized array of U8 values passed as an array by Array Data Pointer; it will do exactly the same thing as far as the DLL function is concerned. To create an empty string, use Initialize Array to create an array of U8, then use Byte Array to String to convert to a string. You should pass the length of that string as the length parameter. This tells the DLL to write the output into that memory, and not to write more than length bytes.
05-06-2020 09:41 AM
Hello All.
I'm new at using tabview to call DLL functions, and I have this structure definition, but my DLL does not accept one or more of the parameters that I defined in my type def.
typedef struct {
unsigned int arbitrationBitRate;
unsigned int sjwAbr; // CAN bus timing for nominal / arbitration bit rate
unsigned int tseg1Abr;
unsigned int tseg2Abr;
unsigned int dataBitRate;
unsigned int sjwDbr; // CAN bus timing for data bit rate
unsigned int tseg1Dbr;
unsigned int tseg2Dbr;
unsigned char reserved; // has to be zero
unsigned char options; // CANFD_CONFOPT_
unsigned char reserved1[2]; // has to be zero
unsigned int reserved2; // has to be zero
} XLcanFdConf;
I'm attaching the ctl defined as I understand. Can someone spot the problem with my definition?
Thank you. Amazing forum.
05-06-2020 11:38 AM
I've been away from C for a long time, but here are the 2 things I think you need to do.
1. Figure out the "bitness" of the dll so you know how many bits there are in an unsigned int. These days, I'd expect it might be either 32 or 64, depending on compiler options. (Back in my time, it was 16 for an int, 8 for a short or a char, 32 for a long).
Then you'll need to change the datatype representation in your typedef to match all the unsigned int fields.
2. You don't want an array of u8's in your LabVIEW typedef. A LabVIEW array datatype includes a prepended 4 byte length before the bytes used for the data itself. The C array won't have the length bytes.
I'd just make 2 consecutive u8 fields with names like reserved_1A and reserved_1B to match the C-style memory layout. (I *think*, but am less than 100% sure, that a LabVIEW cluster with 2 u8 elements would also match the C-style memory layout.)
Beyond that, there's a chance you may also need to account for further compiler options that define how byte boundaries are enforced for structs. (Sometimes struct fields can occupy more memory space than strictly necessary in order to start each field at a multiple of, say, 4 bytes.) I've been away from C compilers far too long to speculate on the likelihood or how to investigate. Just giving you an alert in case things still crash.
-Kevin P
05-07-2020 02:33 PM
""A LabVIEW array datatype includes a prepended 4 byte length before the bytes used for the data itself. The C array won't have the length bytes.""
This helped me a lot to solve the problem. thank you.
05-08-2020 07:33 AM
@trncrboy wrote:
""A LabVIEW array datatype includes a prepended 4 byte length before the bytes used for the data itself. The C array won't have the length bytes.""
That's only very partially true and not even the main problem here! Do you know any C? If you do the LabVIEW data structure you created will pass this datatype to the function:
typedef struct (
int32_t numElm;
uint8_t elm[];
} LVArrayRec, **LVArrayPtr, **LVArrHdl;
typedef struct {
uint8_t arbitrationBitRate;
uint8_t sjwAbr; // CAN bus timing for nominal / arbitration bit rate
uint8_t tseg1Abr;
uint8_t tseg2Abr;
uint16_t dataBitRate;
uint8_t sjwDbr; // CAN bus timing for data bit rate
uint8_t tseg1Dbr;
uint8_t tseg2Dbr;
uint8_t reserved; // has to be zero
uint8_t options; // CANFD_CONFOPT_
LVArrHdl reserved1[2]; // has to be zero
uint8_t reserved2; // has to be zero
} XLcanFdConf;
Pretty much every element in there does not match the data element type in your declaration that you show!! uint8_t is NOT equal to int! It's equal to unsigned char!
And as you can see the LabVIEW array is a handle (a pointer to a pointer to a data structure containing the array data with a prepended 4 byte size integer.
As has been over and over mentioned in this forum in virtually umptien threads, fixed size C arrays embedded in a struct need to be represented in LabVIEW by a cluster with the according number of elements of the correct datatype in there.
And of course you need to make sure that the other elements are correct in size. (unsigned) int is equivalent to an (unsigned) int32 on every LabVIEW platform since the demise of the Windows 3.1 version of LabVIEW.
05-08-2020 09:47 AM
To the OP: listen to @rolfk before listening to me (or practically anyone else). I'd consider him the preeminent active expert around here about these kinds of things (among many others).
-Kevin P