"out string" parameters in XPCOM

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

"out string" parameters in XPCOM

Post by Jay T »

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 by Jay T »

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 by Jay T »

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 by doron »

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)
Contact:

Post by Torisugari »

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

Re: "out string" parameters in XPCOM

Post by rizwan »

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