10-23-2009 05:22 PM
Hi all,
Thanks for taking the time to read and (hopefully) reply.
I'm working with an instrument driver I created from an ActiveX control using the ActiveX Controller Wizard. However, I have a function that won't return one of it's arguments but it will return the other. See below.
The objective is to open up a device called the EV2300. GetFreeBoards() should return the number of devices (boards) found and the names of the boards. It finds and returns the number of devices fine (2 if two devices are connected, 1 if one device connected and 0 when no devices are connected) but where it fails is returning the names. The character array passed in as reference just remains empty and no errors are reported.
char msgStr[256]; char *BrdName; ERRORINFO error; CAObjHandle EV2300_Handle; int returnVal; long nBrdsFound = 0; mainpanel = LoadPanel (0, "TE_User_Interface.uir", MAIN_PANEL); GetObjHandleFromActiveXCtrl (mainpanel, MAIN_PANEL_BQ80XRW, &EV2300_Handle); BrdName = msgStr; returnVal = BQ_EV2300_GetFreeBoards (EV2300_Handle, &error, 16, &nBrdsFound, &BrdName);
The wrapper function generated by the wizard:
HRESULT CVIFUNC BQ_EV2300_GetFreeBoards (CAObjHandle objectHandle,
ERRORINFO *errorInfo,
long nNumBrdsToGet, long *nNumBrds,
char **listBrdNames)
{
HRESULT __result = S_OK;
unsigned int __paramTypes[] = {CAVT_LONG, CAVT_LONG | CAVT_BYREFI,
CAVT_CSTRING | CAVT_BYREFI};
__result = CA_MethodInvokeEx (objectHandle, errorInfo, &BQ_IID_EV2300_,
0x7, CAVT_EMPTY, NULL, 3, __paramTypes,
nNumBrdsToGet, nNumBrds, listBrdNames);
return __result;
}
Using the same ActiveX controller and hardware set-up in VB6 works perfectly: the name of the EV2300 is returned and I can go on to use it in other functions:
Dim Bq80xRW1 As Bq80xRW Dim BrdName As String Dim nBrdsFound As Long Bq80xRW1.GetFreeBoards 16, nBrdsFound, BrdName
Any ideas what I could be doing wrong?
Solved! Go to Solution.
10-24-2009 02:35 AM - edited 10-24-2009 02:36 AM
The most probable reason is that the method invoked expects to receive a pointer to a string, while you are passing a pointer to a pointer of chars which has not been initialized. Visual basic passes all parameters by reference, unless the ByVal keyword is used, so it passes the address of a string (properly dimensioned variable). The documentation of the device driver should inform you whether the function allocates memory for you or not but it probably won't.
If this is true, your code will probably work if you declare
char BrdName[512];
10-26-2009 09:42 AM
I tried your suggestion and recieved this error message when declaring char BrdName[256]:
"Type error in argument 5 to `BQ_EV2300_GetFreeBoards'; found 'pointer to array 256 of char' expected 'pointer to pointer to char'."
LabWindows/CVI wants a pointer to a pointer to char so that's what I've been giving it but I've tried a number of different variations and still nothing.
According to the wrapper code the function expects a CAVT_CSTRING (from the Help: "char * (null-termineated string)") passed by reference (CAVT_BYREFI, "Pointer to data type. Input-only parameter you pass by reference. Defined as CAVT_BYREF | CAVT_IN.").
HRESULT CVIFUNC BQ_EV2300_GetFreeBoards (CAObjHandle objectHandle,
ERRORINFO *errorInfo,
long nNumBrdsToGet, long *nNumBrds,
char **listBrdNames)
{
HRESULT __result = S_OK;
unsigned int __paramTypes[] = {CAVT_LONG, CAVT_LONG | CAVT_BYREFI,
CAVT_CSTRING | CAVT_BYREFI};
__result = CA_MethodInvokeEx (objectHandle, errorInfo, &BQ_IID_EV2300_,
0x7, CAVT_EMPTY, NULL, 3, __paramTypes,
nNumBrdsToGet, nNumBrds, listBrdNames);
return __result;
}
Could the ActiveX Control Wizard be incorrect and the expected parameter types are wrong?
10-26-2009 11:12 AM
Something is definitely amiss, because the last two parameters are both output parameters yet they are being defined as input parameters. So either the ActiveX control has bad IDL in it or the ActiveX controller wizard has made a mistake.
You might try a little experiment by changing the two CAVT_BYREFI references in the __paramTypes array to CAVT_BYREFO to see if that makes a difference. Rationale: for strings, CA_MethodInvokeEx probably has to convert from C string type to BSTR for input parameters, and from BSTR back to C string for output parameters. If it doesn't think a parameter is an output parameter, my guess is it probably won't bother converting back. For longs (which are a native ActiveX type) it doesn't have to do any conversion.
10-26-2009 11:23 AM
10-26-2009 12:02 PM - edited 10-26-2009 12:09 PM
10-11-2010 01:00 PM
I need to raise this thread from the land of a year ago because I'm having the exact same problem. The twist is that I don't have access to the raw wrapper code.
I got the .dll and .oxc files direct from Texas Instruments. I imported it as an activex control using the advance tools menu, and the functions show up, but I can't get them to work.
So, I require the answer for one of two questions:
1) How do I get access to the wrapper code?
2) How do I get the activeX control to work without editing the wrapper directly?
10-11-2010 03:10 PM
Would it be possible to convert the Cstring to a BSTR and vice versa? Since I can't apparently edit the dll wrapper (since I don't have the source code) that sounds like it would solve the problem.
Thanks.
10-11-2010 05:36 PM
Whichever folder you created your instrument (.fp) in should also have .c and .h files of the same name. The wrappers are in the .c file.
10-12-2010 07:24 AM
I didn't create an instrument folder.
I imported the dll into an activeX control to the Palette using the Tools menu. The DLL was in my win32 folder, and there was no header file associated with it because it was generated for VB6 (It works with VB6 code, incidentally). Then I added an ActiveX VI from the Connectivity Palette, followed by tying it to the ActiveX control associated with the DLL, and selecting the method I want to invoke. This has the downside that there isn't a help file for any of the invoke methods, but since I'm familiar with how they work in VB6 I should be able to figure most of it out.
The problem I'm having is that GetFreeBoards doesn't return anything useful, and I can't use the output of the string output with the OpenDevice function that requires a device name.
I'm very new to Labview (I'm using 8.5, if that helps. My plan is to upgrade to the latest version soon.) so if a folder was created that has the .h and .c files in it, I don't know where that would be.