Thread overview
Using out qualifier instead of *, how to pass null?
Feb 01, 2007
Rick Mann
Feb 01, 2007
Kirk McDonald
Feb 01, 2007
Derek Parnell
Feb 01, 2007
xs0
Feb 02, 2007
Derek Parnell
February 01, 2007
In wrapping this C API, I've been going back and forth between converting "Foo*" output parameters to "out Foo". I prefer the latter, as I don't have to take the address at the call site, but I don't seem to be able to pass null (which the API allows, meaning, "I'm not interested in this return value").

Am I just stuck with Foo*? Alternatively, I can overload the C function with D wrappers, I suppose. Hmm. That's probably best.
February 01, 2007
Rick Mann wrote:
> In wrapping this C API, I've been going back and forth between converting "Foo*" output parameters to "out Foo". I prefer the latter, as I don't have to take the address at the call site, but I don't seem to be able to pass null (which the API allows, meaning, "I'm not interested in this return value").
> 
> Am I just stuck with Foo*? Alternatively, I can overload the C function with D wrappers, I suppose. Hmm. That's probably best.

You can't pass it null, for the same reason that you can't pass null to a C++ function with a reference parameter.

I would recommend binding the C API as closely as you can, and then using D's features in a wrapper around it. Generally speaking, this will be the most robust and portable approach. It will give you the convenient D version for most uses, and the raw C version when you need that.

-- 
Kirk McDonald
Pyd: Wrapping Python with D
http://pyd.dsource.org
February 01, 2007
Kirk McDonald wrote:

> I would recommend binding the C API as closely as you can, and then using D's features in a wrapper around it. Generally speaking, this will be the most robust and portable approach. It will give you the convenient D version for most uses, and the raw C version when you need that.

Having just rewritten parts of wxD, I second recommending that approach.
(for wxWidgets it had to be done anyway, because it's a C++ API library,
but generally speaking it is easier to keep each language to its own...)
This normally also includes offering legacy aliases, for C portability.

--anders

PS. Rick, for your API wrapper you might find this article interesting:
http://www.eclipse.org/articles/Article-SWT-Design-1/SWT-Design-1.html
Bonus points are awarded for completing the Mac OS X DWT port to Carbon,
that Carlos started on: http://dsource.org/forums/viewtopic.php?t=1169
February 01, 2007
On Thu, 01 Feb 2007 03:00:01 -0500, Rick Mann wrote:

> In wrapping this C API, I've been going back and forth
> between converting "Foo*" output parameters to "out Foo".
> I prefer the latter, as I don't have to take the address
> at the call site, but I don't seem to be able to pass null
> (which the API allows, meaning, "I'm not interested in
> this return value").
> 
> Am I just stuck with Foo*? Alternatively, I can overload the C function with D wrappers, I suppose. Hmm. That's probably best.

Is not possible to use a 'null' object ... ?


class Foo {}
void Bar(out Foo f)
{
  if (f is null)
      ...
  else
      ...
}
Foo NullFoo;
Foo RealFoo = new Foo;

Bar(NullFoo);
Bar(RealFoo);

-- 
Derek Parnell
February 01, 2007
Derek Parnell wrote:

>>Am I just stuck with Foo*? Alternatively, I can overload
>>the C function with D wrappers, I suppose. Hmm. That's
>>probably best.
> 
> Is not possible to use a 'null' object ... ?

Probably not to extern C, without a D wrapper ?

--anders
February 01, 2007
Derek Parnell wrote:
> On Thu, 01 Feb 2007 03:00:01 -0500, Rick Mann wrote:
> 
>> In wrapping this C API, I've been going back and forth
>> between converting "Foo*" output parameters to "out Foo". I prefer the latter, as I don't have to take the address
>> at the call site, but I don't seem to be able to pass null
>> (which the API allows, meaning, "I'm not interested in
>> this return value").
>>
>> Am I just stuck with Foo*? Alternatively, I can overload
>> the C function with D wrappers, I suppose. Hmm. That's
>> probably best.
> 
> Is not possible to use a 'null' object ... ?
> 
> 
> class Foo {}
> void Bar(out Foo f) {   if (f is null)
>       ...    else
>       ...
> }
> Foo NullFoo;
> Foo RealFoo = new Foo;
> 
> Bar(NullFoo);
> Bar(RealFoo);

hmm.. doesn't out cause (f is null) to be always true in that code?


xs0
February 02, 2007
On Fri, 02 Feb 2007 00:38:30 +0100, xs0 wrote:

> Derek Parnell wrote:
>> On Thu, 01 Feb 2007 03:00:01 -0500, Rick Mann wrote:
>> 
>>> In wrapping this C API, I've been going back and forth
>>> between converting "Foo*" output parameters to "out Foo".
>>> I prefer the latter, as I don't have to take the address
>>> at the call site, but I don't seem to be able to pass null
>>> (which the API allows, meaning, "I'm not interested in
>>> this return value").
>>>
>>> Am I just stuck with Foo*? Alternatively, I can overload the C function with D wrappers, I suppose. Hmm. That's probably best.
>> 
>> Is not possible to use a 'null' object ... ?
>> 
>> class Foo {}
>> void Bar(out Foo f)
>> {
>>   if (f is null)
>>       ...
>>   else
>>       ...
>> }
>> Foo NullFoo;
>> Foo RealFoo = new Foo;
>> 
>> Bar(NullFoo);
>> Bar(RealFoo);
> 
> hmm.. doesn't out cause (f is null) to be always true in that code?

LOL... yes it does. I was concentrating on the problem - "I don't seem to be able to pass null", but missed that obvious gotcha. This code below actually works though...

// ------------
import std.stdio;

class Foo
{
    char[] m_id;

    this(char[] x) { m_id = x.dup; }
}
void Bar(inout Foo f)
{
  if (f is null)
      writefln("NULL");
  else
      writefln("Got %s", f.m_id);
}
void main()
{
    Foo NullFoo;
    Foo FooA = new Foo("Fred");
    Foo FooB = new Foo("Betty");

    Bar(NullFoo);
    Bar(FooB);
    Bar(FooA);
}
// ------------

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocrity!"
2/02/2007 11:04:56 AM