NI TestStand

cancel
Showing results for 
Search instead for 
Did you mean: 

Synchronous UIMessage Question

Hi John,

Glad it worked. Basically, the issue is that ActiveX objects can support many different interfaces. The one interface that every object has to support is IUnknown. Converting the IUnknown ptr the way you were, you were basically taking the IUnknown interface and making an equivalent CVI objhandle for it, however, the wrapper functions for the syncmanager class are expecting to get an objhandle for the ISyncManager interface. The CA_CreateObjHandleFromInterface() function allows you to specify exactly which interface on the object you want to make an objhandle for. This allows you to specify that you want the ISyncManager interface rather than the IUnknown one. The CA_CreateObjHandleFromInterface() calls a special method, QueryInterface(), on the IUnknown pointer to get the interface you requested. Every interface implements QueryInterface so that you can get any other interface an object supports from whichever one you have.

One thing to note is that all interfaces can also be treated like IUnknown because they are really a superset of the IUnknown interface which is where things get confusing. Basically, an LPUNKNOWN pointer could really point to any interface, only by using QueryInterface (or
CA_CreateObjHandleFromInterface in CVI) can you be sure you are getting the one you want. Hope that wasn't too confusing :).

-Doug

0 Kudos
Message 11 of 18
(1,849 Views)
Doug,
That wasn't confusing at all. Now that you've explained it, it makes perfect sense. In my exploration of ActiveX, I learned that each ActiveX control can support multiple interfaces which can be obtained via the Query method. I just really didn't connect it with the Synch manager. The documentation simply tells you that LPUNKNOWN is returned. It would have been nice if they would have listed what possible interfaces are available and how to get and use them. The NI documentation on this stuff is a little lacking in these areas or I am not looking in the right places. If you don't know exactly what you are looking for, you won't ever find it. I've really noticed this about most ActiveX controls that I have worked with. There seems to be a lack of good documentation. Smiley Happy
Again, thanks,
John
0 Kudos
Message 12 of 18
(1,843 Views)

Hello guys,

 

I have a question about the convertion between different data types.

I have created an object handle CAObjHandle instrumentConfiguration.

And this handle has been initialized porperly by calling a function in an ActiveX conreoller.

 When I tried to use it in another function I was getting trouble.

 

return_status = ConfigAdviserAdvise (testset, NULL, instrumentConfiguration, &instrumentConfigCookie);

The 3rd parameter -instrumentConfiguration- in this function is requiring an LPUNKNOWN data type but not CAObjHandle.

 

Do you have any idea about how to convert the CAObjHandle to LPUNKNOWN data type?

 

Thanks,

 

Eric

0 Kudos
Message 13 of 18
(1,528 Views)

I think the function you are looking for is CA_GetInterfaceFromObjHandle(). I think you can use IID_IUnknown as the interface Id. Check the didAddRef parameter, if it's true (which I think it probably will be in this case unless you pass the actual interface id instead of IID_IUnknown which should work too if you prefer) then you will need to call Release() on the pointer once you are done with it.

 

Hope this helps,

-Doug

0 Kudos
Message 14 of 18
(1,516 Views)

Thanks Doug. I tried to use the function you provided. But I was not sure i have passing the parameters in a right way. Here is the piece of code I was using.

 

CAObjHandle instrumentConfiguration = 0;      
long instrumentConfigCookie = 0;
LPUNKNOWN *instrumentConfiguration_lpunknown;
const IID *IID_IUnknown;
int *didAddRef;                                         
 
// 1- Initialize the ActiveX object: instrumentConfiguration
return_status = GENERICINSTRUMENTSLib_IInstrumentConfigurationInitialize (instrumentConfiguration, NULL, configFile);
  
//2- Obtain interface pointer(instrumentConfiguration_lpunknown) with LPUNKNOWN data type from instrumentConfiguration object 
return_status = CA_GetInterfaceFromObjHandle (instrumentConfiguration, IID_IUnknown, 0, &instrumentConfiguration_lpunknown,&didAddRef);

 

//3- Pass the instrumentConfiguration_lpunknown pointer to AGILENT8960Lib_IInstrConfigAdviserAdvise and obtain a pointer to instrumentConfigCookie
//This function requires a LPUNKNOWN type of pointer and that's why I want to get a pointer with LPUNKNOWN type but not the CAObjHandle data type   
return_status = AGILENT8960Lib_IInstrConfigAdviserAdvise (testset, NULL, instrumentConfiguration_lpunknown, &instrumentConfigCookie);

 

Question for step 2 is that I don't know how I should initialize the parameter IID_IUnknown. My understanding is this is a parameter that tells you what type

of pointer you want to be returned and it should be some kind of const number. But what is the const number that is correlated to LPUNKNOWN type?

 

Thanks,

Eric

0 Kudos
Message 15 of 18
(1,507 Views)

Hi Eric,

 

For step 2, I didn't mean to create a new constant, the Windows header files should have one already defined (I think if you are including cviauto.h you should already have it). Also, you should not declare a pointer for didAddRef, that will corrupt memory if you pass that, what you need to pass for that parameter is the address of an integer (use the & operator). Also you should initialize the unknown pointer to NULL and you shouldn't have an LPUNKNOWN * just an LPUNKNOWN (LPUNKNOWN Is already a typedef to IUnknown *). Also, you should release the pointer once you are done with it if needed. Your code should look something like this (you don't have to use errChk() macros for error handling, but it's a good idea to check the return values and handle errors):

 

int error = 0;

CAObjHandle instrumentConfiguration = 0;      
long instrumentConfigCookie = 0;
LPUNKNOWN instrumentConfiguration_lpunknown = NULL;
int didAddRef;                                         
 
// 1- Initialize the ActiveX object: instrumentConfiguration
errChk(GENERICINSTRUMENTSLib_IInstrumentConfigurationInitialize (instrumentConfiguration, NULL, configFile));

 
//2- Obtain interface pointer(instrumentConfiguration_lpunknown) with LPUNKNOWN data type from instrumentConfiguration object 
errChk(CA_GetInterfaceFromObjHandle (instrumentConfiguration, &IID_IUnknown, 0, &instrumentConfiguration_lpunknown, &didAddRef));

 

//3- Pass the instrumentConfiguration_lpunknown pointer to AGILENT8960Lib_IInstrConfigAdviserAdvise and obtain a pointer to instrumentConfigCookie
//This function requires a LPUNKNOWN type of pointer and that's why I want to get a pointer with LPUNKNOWN type but not the CAObjHandle data type   
errChk(AGILENT8960Lib_IInstrConfigAdviserAdvise (testset, NULL, instrumentConfiguration_lpunknown, &instrumentConfigCookie));

 

Error:

 

// 4- release the pointer if needed

 

if (instrumentConfiguration_lpunknown != NULL && didAddRef)

     instrumentConfiguration_lpunknown->lpVtbl->Release(instrumentConfiguration_lpunknown);

 

 

Hope this helps,

-Doug

0 Kudos
Message 16 of 18
(1,486 Views)

Thanks Doug. I was following your instructions and it really works. But I can't get the expected response for configFile. It's supposed to be a long number instead of 0.

 

GENERICINSTRUMENTSLib_IInstrumentConfigurationInitialize (instrumentConfiguration, NULL, configFile);

I guess there is something I haven't done properly before calling this function.

 

 

Anyways the type conversion for instrumentConfiguration is working properly and I have learned a lot from you. Thanks a lot.

 

 

Eric 

0 Kudos
Message 17 of 18
(1,472 Views)

You should be passing the address of the configFile variable into the function if it is an output parameter. You are currently just passing it by value so it can't really get set inside the function anyway.

 

I'm not sure what the data type of configFile is in your case (probably should be CAObjHandle or something), but if you are expecting to get configFile as an output parameter the call should look like this:

 

 GENERICINSTRUMENTSLib_IInstrumentConfigurationInitialize (instrumentConfiguration, NULL, &configFile);

 

Basically, in C, in order for a variable to be set inside a function you have to pass the address of the variable into the function.

 

Anyway, glad I could be of help. Hopefully this will fix you final problem.

-Doug

0 Kudos
Message 18 of 18
(1,469 Views)