Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Type mismatch in return from COM object
#1
Hi -

I think I'm missing something but I've already had my cup of coffee & that didn't help Big Grin

I've created a COM object in C# (it invokes a web service with NTLM authentication) and the values appear to be successfully being returned to QM. But I think I'm running into a type conversion problem.

The type is defined in C#. The type information is visible in QM when I'm writing code. And - if I use a simple "out" statement it prints the correct value. But if I use a more complex out statement it does not.

Here's what the call looks like:
WebServiceWrapper.iStudyData studyData1 = pacsWebServices.getStudyData(testAccessionOK)
and one of the values in studyData1 is the string "PatientName".

The following statement will print the correct value:
Code:
Copy      Help
out studyData1.PatientName
and the following will also work:
Code:
Copy      Help
str name = studyData1.PatientName
out "studyData1.PatientName %s" name

But both of these will fail:
Code:
Copy      Help
out F"studyData1.PatientName {studyData1.PatientName}"
and
Code:
Copy      Help
out "studyData1.PatientName %s" studyData1.PatientName
with the error message
Error (RT) in TestPacsInterface: 0x80020005, Type mismatch.

In C# I've defined the API to this class like this:
Code:
Copy      Help
[Guid("xxxxxx-xxxxx-xxxxxxx"), ClassInterface(ClassInterfaceType.AutoDual)]
    [ComVisible(true)]
    public class iStudyData
    {
        public string StudyRef;
        public string PatientName;
        ...
   }
.

Any ideas what's wrong? I'm worried that this is a symptom that there's a problem with how I've defined the type. Thanks.
#2
C# string type is BSTR type in QM. Only few QM functions support BSTR directly. In other cases assign to a str variable.

BSTR b
str s=b ;;OK
out b ;;OK
out "%s" b ;;error
out F"{b}" ;;error

Similarly, C# object type is VARIANT type in QM. Assign to str, int etc.

If in QM the COM interface variable type is IDispatch, all COM functions will return VARIANT.
#3
Thanks. Works perfectly.
#4
I have a followup question about memory management.

I have created parallel data structures in QM and C# (Types in QM, Classes in C#). I assign the returned values from the C# COM object into their QM Types so that the BSTR are converted to str values. This all works fine but I don't understand the memory lifecycle. Do I need to free the pacsWebServices object allocated with _create

Member function EMIPacsWebService.GetPacsUser
Code:
Copy      Help
PACSWebServiceWrapper.PACSWebInterface pacsWebServices
pacsWebServices._create

or the pacsLogin C# object returned from the DLL?

Member function EMIPacsWebService.GetPacsUser
Code:
Copy      Help
PACSWebServiceWrapper.iPacsLogin pacsLogin = pacsWebServices.getPacsLogin(hostname);; Call to COM object

Here's the entire function for context:

Member function EMIPacsWebService.GetPacsUser
Code:
Copy      Help
function str'hostname TUserHistory'&sUserHistory ;; Returns the PACS user for this station

#compile "RadFusionTypes"

typelib PACSWebServiceWrapper {xxx-xx-xxxxx} 1.0

PACSWebServiceWrapper.PACSWebInterface pacsWebServices
pacsWebServices._create
str baseURL = this.baseURL
;out F"endpoint {baseURL}"
pacsWebServices.setEndPointAddress( baseURL)

PACSWebServiceWrapper.iPacsLogin pacsLogin = pacsWebServices.getPacsLogin(hostname);; Call to COM object
if (pacsLogin)
,if (pacsLogin.NetworkStatus)
,,sUserHistory.NetworkStatus.StatusCode = pacsLogin.NetworkStatus.statusCode
,,sUserHistory.NetworkStatus.StatusReason = pacsLogin.NetworkStatus.statusReason
,,if (sUserHistory.NetworkStatus.statusCode = 200)
,,,sUserHistory.AeRef = pacsLogin.AeRef
,,,sUserHistory.FailedLoginDateTime = pacsLogin.FailedLoginDateTime
,,,sUserHistory.Host = pacsLogin.Host
,,,sUserHistory.LoginDateTime = pacsLogin.LoginDateTime
,,,sUserHistory.LogoutDateTime = pacsLogin.LogoutDateTime
,,,sUserHistory.UserId = pacsLogin.UserId
,,else
,,,str reason = pacsLogin.NetworkStatus.statusReason
,,,int code = pacsLogin.NetworkStatus.statusCode
,,,out F"Failed to retrieve getPacsLogin for hostname {hostname} because status code {code} reason {reason}"
,else
,,out F"Failed to retrieve getPacsLogin for hostname {hostname} null network status returned"
,,sUserHistory.NetworkStatus.StatusCode = 500
,,sUserHistory.NetworkStatus.StatusReason = "Null network status returned"
else
,out F"Failed to retrieve getPacsLogin for hostname {hostname} null object returned"    
,sUserHistory.NetworkStatus.StatusCode = 500
,sUserHistory.NetworkStatus.StatusReason = "Null object returned from DLL"
,,

Thanks!
#5
Don't need to free COM objects explicitly. QM calls Release() when the variable dies. Normally then the COM object deletes self. The C# object will be freed by the garbage collector later.
QM also frees memory of str, BSTR, VARIANT etc when the variable dies.


Forum Jump:


Users browsing this thread: 1 Guest(s)