04-12-2009 11:48 AM
Hello,
I need to communicate to an external DLL function which accepts an integer and a pointer to a structure. My understanding is that based on the integer value, the structure data is updated.
How do I send the pointer to DLL? How to get the updated value in Labview? how to achieve this in Labview CLN?
Regards
Gopal
04-13-2009 11:31 AM
i've never had to do that before but the first thing i would try (and you might have already) is passing a reference to the DLL.
another thing that might work is finding a function that would return the same kind of data type as the pointer and then from that trying to morph the data into that type that is returned...but now i am curious as to how that might work as i know i will be in the future interfacing with others' DLLs as well.
04-14-2009 08:40 AM
04-14-2009 09:33 AM
One way to pass a structure pointer is to use a cluster on the diagram and use the 'adapt to type' feature of the Call Library Node. You can also generate a .c file to double-check the structure definition. Here are some important items to keep in mind:
04-18-2009 01:13 AM
Hello,
Thank you for the detailed info. But can you suggesst the method for the following data.
The following are the details of the data structure the function reference as defined in the API documentation. I want to know how to pass the details to the dll and get the information back for this structure.
typedef struct _BLUETOOTH_DEVICE_INFO_EX {
DWORD dwSize;
BYTE address[DEVICE_ADDRESS_LENGTH];
BYTE classOfDevice[DEVICE_CLASS_LENGTH];
CHAR szName[MAX_DEVICE_NAME_LENGTH];
BOOL bPaired;
UCHAR ucLmpVersion;
WORD wManuName;
WORD wLmpSubversion;
BYTE reserved[16];
WORD wClockOffset;
BOOL bConnected;
DWORD dwDataRecvBytes;
DWORD dwDataSentBytes;
CHAR cSignalStrength;
} BLUETOOTH_DEVICE_INFO_EX, *PBLUETOOTH_DEVICE_INFO_EX;
DWORD BT_GetLocalDeviceInfo (
/* [in] */ DWORD dwMask,
/* [out] */ PBLUETOOTH_DEVICE_INFO_EX pDevInfo
);
Regards
Gopal
04-18-2009 09:14 AM
The following are the details of the data structure the function reference as defined in the API documentation. I want to know how to pass the details to the dll and get the information back for this structure.
typedef struct _BLUETOOTH_DEVICE_INFO_EX {
DWORD dwSize;
BYTE address[DEVICE_ADDRESS_LENGTH];
BYTE classOfDevice[DEVICE_CLASS_LENGTH];
CHAR szName[MAX_DEVICE_NAME_LENGTH];
BOOL bPaired;
UCHAR ucLmpVersion;
WORD wManuName;
WORD wLmpSubversion;
BYTE reserved[16];
WORD wClockOffset;
BOOL bConnected;
DWORD dwDataRecvBytes;
DWORD dwDataSentBytes;
CHAR cSignalStrength;
} BLUETOOTH_DEVICE_INFO_EX, *PBLUETOOTH_DEVICE_INFO_EX;
DWORD BT_GetLocalDeviceInfo (
/* [in] */ DWORD dwMask,
/* [out] */ PBLUETOOTH_DEVICE_INFO_EX pDevInfo
);
There are a few approaches to take here, with various levels of tedium / non-LabVIEW effort. It's unfortunate that LV's built-in Bluetooth functions don't offer this level of detail - as far as I know.
Approach I:
Write a wrapper DLL of your own. The roles of the DLL are to act as a data structure translator and to cope with situations LV can't support directly from the diagram (e.g. passing callback functions to functions, etc.). The main drawback, of course, is dealing in C code with data types like LStrHandle and whatnot.
Approach II:
Rely on a C struct being the same as a LV cluster. In this particular case, you have to deal with fixed-sized blocks within the C structure, such as BYTE address[DEVICE_ADDRESS_LENGTH]. The way to do this is to treat each fixed-sized array as a cluster as well. So the 'address' element of your LV cluster would itself be a cluster containing DEVICE_ADDRESS_LENGTH uInt8-sized numeric values. You'll also have to be sure to set the dwSize parameter to the size IN BYTES of the entire cluster's data. I believe in Win32 the BOOL type is a 32-bit integer sized quantity - the rest should be apparent. Provided you accurately compute and set the dwSize element, this approach should work. In this case, you're taking advantage of the fact that a struct containing N of the same elements of type T looks the same in memory as a fixed-sized array of N elements of the data type T.
Approach III:
Make an array of bytes large enough for the structure and pass it as a simple data pointer. You'll have to fill in the first four bytes correctly with the size of the C structure, just as in Approach II, but you could make the array larger than necessary. After the call, extract the separate structure members by hand, possibly needing to fix up the byte ordering (it's little endian in Windows).Though this sounds really onerous, if you only need one or two things out of the structure, it may be less work to implement than the other two suggestions.
04-19-2009 08:26 AM
Hello,
Thank your for the response. I tried the approach 3. But not much success. I tired to pass the array input as 'array data pointer' in CLN.
Iam trying to build a kind of bluetooth coder, where I can test the common bluetooth profiles automatically.
Do you have any suggesstion on this?
Regards
Gopal
04-20-2009 11:19 AM
Did you also verify the calling conventions for the function? (C vs. Pascal (a.k.a. WINAPI)) Also, the first four entries in that array of bytes will need to be in the proper order to specify the structure size.
I did a test on a machine here... but I don't have any Bluetooth devices or accessibility. I get error code 3 back - which kind of makes sense, since the machine has no BT capability.
Here's a screenshot. I ran this VI after calling the BT_InitializeLibrary function.
04-20-2009 12:52 PM
For what it's worth, I also made a cluster version and got the same results. I've attached an image of the diagram. The following is the resulting C structure passed to the DLL, created using the 'create .c file...' feature of the Call Library Node. I often use that as a sanity-check to verify this type of approach.
/* Call Library source file */
#include "extcode.h"
/* Typedefs */
typedef struct {
uint8_t _0;
uint8_t _1;
uint8_t _2;
uint8_t _3;
uint8_t _4;
uint8_t _5;
} TD2;
typedef struct {
uint8_t _0;
uint8_t _1;
uint8_t _2;
} TD3;
typedef struct {
uint8_t _00;
uint8_t _11;
uint8_t _22;
uint8_t _33;
uint8_t _44;
uint8_t _55;
uint8_t _66;
uint8_t _77;
uint8_t _88;
uint8_t _99;
uint8_t _110;
uint8_t _111;
uint8_t _112;
uint8_t _113;
uint8_t _114;
uint8_t _115;
uint8_t _116;
uint8_t _117;
uint8_t _118;
uint8_t _119;
uint8_t _220;
uint8_t _221;
uint8_t _222;
uint8_t _223;
uint8_t _224;
uint8_t _225;
uint8_t _226;
uint8_t _227;
uint8_t _228;
uint8_t _229;
uint8_t _330;
uint8_t _331;
uint8_t _332;
uint8_t _333;
uint8_t _334;
uint8_t _335;
uint8_t _336;
uint8_t _337;
uint8_t _338;
uint8_t _339;
uint8_t _440;
uint8_t _441;
uint8_t _442;
uint8_t _443;
uint8_t _444;
uint8_t _445;
uint8_t _446;
uint8_t _447;
uint8_t _448;
uint8_t _449;
uint8_t _550;
uint8_t _551;
uint8_t _552;
uint8_t _553;
uint8_t _554;
uint8_t _555;
uint8_t _556;
uint8_t _557;
uint8_t _558;
uint8_t _559;
uint8_t _660;
uint8_t _661;
uint8_t _662;
uint8_t _663;
} TD4;
typedef struct {
uint8_t _00;
uint8_t _11;
uint8_t _22;
uint8_t _33;
uint8_t _44;
uint8_t _55;
uint8_t _66;
uint8_t _77;
uint8_t _88;
uint8_t _99;
uint8_t _110;
uint8_t _111;
uint8_t _112;
uint8_t _113;
uint8_t _114;
uint8_t _115;
} TD5;
typedef struct {
uint32_t dwSize;
TD2 address;
TD3 classOfDevice;
TD4 szName;
uint32_t bPaired;
uint8_t ucLmpVersion;
uint16_t wManuName;
uint16_t wLmpSubversion;
TD5 reserved;
uint16_t wClockOffset;
uint32_t bConnected;
uint32_t dwDataRecvBytes;
uint32_t dwDataSentBytes;
int8_t cSignalStrength;
} TD1;
uint32_t BT_GetLocalDeviceInfo(uint32_t dwMask, TD1 *pDevInfo);
uint32_t BT_GetLocalDeviceInfo(uint32_t dwMask, TD1 *pDevInfo)
{
/* Insert code here */
}
Hope this has helped.
04-21-2009 01:17 PM
Hello,
The cluster worked properly. It returned the value in the output cluster.
It was amazing from your side to identify the dll yourself (I would like to know that secret.).
I have attached my trial VI here.
Will keep you updated as my work progresses...
Thanking You
Gopal