MozillaZine

"out string" parameters in XPCOM

Discuss building things with or for the Mozilla Platform.
Jay T
 
Posts: 79
Joined: May 26th, 2005, 9:25 am

Post Posted August 24th, 2005, 7:10 am

I'm new to XPCOM and have been trying to write a simple method that returns a string. So far, I haven't been able to get it working, so I'm hoping that one of the XPCOM experts on this forum could tell me what I'm doing wrong and help me solve this problem.

I've tried writing the method in two slightly different ways. All my code is based on code I found at http://www.mozilla.org/scriptable/faq.html#i9. In fact, I pretty much copied and pasted the code without changing it.

Here are my two method declarations in my .idl file.
IMyComponent.idl
Code: Select all
string GetStringA();
void GetStringB(out string s);

The xpidl utility produces the following method declarations in the resulting header file.
IMyComponent.h
Code: Select all
/* string GetStringA (); */
NS_IMETHOD GetStringA(char **_retval) = 0;

/* void GetStringB (out string s); */
NS_IMETHOD GetStringB(char **s) = 0;
 string s);

Note that the underlying C++ methods are exactly the same except for the name of the parameter.

And here's the implementation of the two methods.
MyComponent.cpp
Code: Select all
/* string GetStringA (); */
NS_IMETHODIMP MyComponent::GetStringA(char **_retval)
{
   const char* message = "Hello from GetStringA!";
   
    if(!_retval)
        return NS_ERROR_NULL_POINTER;
   
    *_retval = (char*) nsMemory::Clone(message, sizeof(char)*(strlen(message)+1));
    return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}

/* void GetStringB (out string s); */
NS_IMETHODIMP MyComponent::GetStringB(char **s)
{
   const char* message = "Hello from GetStringB!";
   
    if(!s)
        return NS_ERROR_NULL_POINTER;
   
    *s = (char*) nsMemory::Clone(message, sizeof(char)*(strlen(message)+1));
    return *s ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}

This code builds without error. Since I found it on a Mozilla website, I assume it's correct and does what I intend it to do.

The problem is actually loading and using the component in JavaScript. I've tried all sorts of variations, but I haven't been able to get anything to work. To the best of my obviously faulty understanding, this code should work -- although it actually doesn't.
MyComponentTest.js
Code: Select all
var sA;
sA = obj.GetStringA();
alert(sA);
      
var sB = {};
obj.GetStringB(sB);
alert(sB.value);

I don't see anything when the code runs -- neither alert box comes up.

I've been reading some documentation on the nsEmbedString class. Should I be using nsEmbedString objects here? If so, how?

Can anybody see what I'm doing wrong and let me know how to fix it? I'd be very grateful for any help.

Thanks,
Jay

Jay T
 
Posts: 79
Joined: May 26th, 2005, 9:25 am

Post Posted August 24th, 2005, 7:23 am

As a followup, I find the following message in the Firefox JavaScript Console when I try calling either of the methods:

Error: uncaught exception: [Exception... "Component returned failure code: 0x8007000e (NS_ERROR_OUT_OF_MEMORY) [IMyComponent.GetStringA]" nsresult: "0x8007000e (NS_ERROR_OUT_OF_MEMORY)" location: "JS frame :: file:///C:/Homer/Firefox/xpcom-sample/MyComponentTest.js :: MyComponentTestGo :: line 21" data: no]

Same error message for GetStringB.

So it might not be the the JavaScript code that's broken, but rather the underlying C++ code in the implementation of GetStringA and GetStringB. (The JavaScript code still might be broken, but that's not the immediate cause of the failure.)

Jay T
 
Posts: 79
Joined: May 26th, 2005, 9:25 am

Post Posted August 24th, 2005, 9:43 am

OK, I figured it out. At least in the sense that I got it to work. I'd still appreciate any XPCOM experts looking at this code and warning me about any problems I may be introducing. My understanding of string handling in XPCOM is hazy at best, so I may well be doing all sorts of bad things like leaking memory without knowing it.

The key to getting things to work was changing the data type in the .idl file from string to AString. This resulted in the following code.
IMyComponent.idl
Code: Select all
AString GetStringA();
void GetStringB(out AString s);

IMyComponent.h
Code: Select all
/* AString GetStringA (); */
NS_IMETHOD GetStringA(nsAString & _retval) = 0;

/* void GetStringB (out AString s); */
NS_IMETHOD GetStringB(nsAString & s) = 0;

MyComponent.cpp
Code: Select all
/* AString GetStringA (); */
NS_IMETHODIMP JayComponent::GetStringA(nsAString & _retval)
{
   const wchar_t* message = L"Hello from GetStringA!";
   _retval.Assign(message);
   return NS_OK;
}

/* void GetStringB (out AString s); */
NS_IMETHODIMP JayComponent::GetStringB(nsAString & s)
{
   const wchar_t* message = L"Hello from GetStringB!";
   s.Assign(message);
   return NS_OK;
}

The JavaScript code is correct as given above.

I'd be interested in whether I could somehow internally use a regular 1-byte ASCII char string instead of the 2-byte wchar_t string I ended up using in the method implementations. I tried this code like this:
Code: Select all
const char* message = "Hello from GetStringA!";
s.Assign(NS_ConvertASCIItoUTF16(message));

which built fine but crashed when I ran it. Anybody have any ideas why?

doron
 
Posts: 935
Joined: November 4th, 2002, 4:50 pm

Post Posted August 24th, 2005, 12:06 pm

you could do:

_retval.AssignLiteral("My little string")

Also, might want to look at CopyASCIItoUTF16 (http://www.mozilla.org/projects/xpcom/string-guide.html)
If you see a marquee, clap your hands!

Torisugari
 
Posts: 1634
Joined: November 4th, 2002, 8:34 pm
Location: Kyoto, Nippon (GMT +9)

Post Posted August 24th, 2005, 10:23 pm

doron:
IIRC, both CopyASCIItoUTF16(or CopyUTF8toUTF16) and AssignLiteral do not work with Gecko SDK, so I'm afraid they are not useful for third-party developers.

rizwan
 
Posts: 29
Joined: September 19th, 2008, 12:30 am

Post Posted October 17th, 2008, 12:15 am

Any body got its solution? Please mail me at rizwan_nuces@yahoo.com
Thanks in advanced

Return to Mozilla Development


Who is online

Users browsing this forum: No registered users and 1 guest