Dave Dribin
2005-10-04 16:57:18 UTC
Hi fellow SWIG users,
I'm trying to wrap a C++ API that uses Boost shared pointers heavily
for use in C#. Let's say I have two C++ classes Foo and Bar:
class Foo { // ...
};
typedef boost::shared_ptr<Foo> FooPtr;
class Bar {
public:
FooPtr createFoo(...);
int useFoo(FooPtr foo);
};
Now, in my C# code, it would get used like:
Bar bar = new Bar();
FooPtr foo = createFoo();
bar.useFoo(foo);
This works, but I have a couple problems with it. First, FooPtr is
just an ugly name in C#. It would be nice to be able to deal with
classes named Foo and Bar in C#, as FooPtr is just a side effect of
using shared_ptr. I can do some fancy SWIG renaming, but that doesn't
help the second problem. And that problem is that while Foo objects
can be created from Bar, that's only a convenience. A user could just
as easily create a Foo object manually. In C++, it's not so bad:
FooPtr foo(new Foo());
bar->useFoo(foo);
But in C#, this requires:
FooPtr foo = new FooPtr(new Foo());
bar.useFoo(foo);
Even if I did some fancy renaming, it would be:
Foo foo = new Foo(new FooImpl());
bar.useFoo(foo);
That whole double-new thing really is ugly and cumbersome. And it also
introduces some memory management issues. C# will try and delete the
Foo object, even though the pointer is now owned by FooPtr, and I get a
double-free at some point.
I have complete control over the Foo and Bar APIs and I'm willing to
make changes to make this more SWIG-able. I still want to use
shared_ptr as it greatly simplifies memory management. Has anyone else
come across this issue and if so, what was their solutions?
The only solution I've come up with so far is to not expose shared_ptr
objects to end users by doing a PIMPL implementation, with the private
implementation pointer being a shared_ptr. This works beautifully, and
is easily SWIG-able. But it's somewhat of a pain to maintain because
the main and Impl class have common methods that need to be repeated.
In the interest of the Don't Repeat Yourself (DRY) concept, I'd like to
avoid that. But barring any other suggestions, the PIMPL route is the
way I'm going to go. It works for SWIG and yet keeps C++ memory
management sane and exception safe.
-Dave
_______________________________________________
Swig maillist - ***@cs.uchicago.edu
http://mailman.cs.uchicago.edu/mailman/listinfo/swig
I'm trying to wrap a C++ API that uses Boost shared pointers heavily
for use in C#. Let's say I have two C++ classes Foo and Bar:
class Foo { // ...
};
typedef boost::shared_ptr<Foo> FooPtr;
class Bar {
public:
FooPtr createFoo(...);
int useFoo(FooPtr foo);
};
Now, in my C# code, it would get used like:
Bar bar = new Bar();
FooPtr foo = createFoo();
bar.useFoo(foo);
This works, but I have a couple problems with it. First, FooPtr is
just an ugly name in C#. It would be nice to be able to deal with
classes named Foo and Bar in C#, as FooPtr is just a side effect of
using shared_ptr. I can do some fancy SWIG renaming, but that doesn't
help the second problem. And that problem is that while Foo objects
can be created from Bar, that's only a convenience. A user could just
as easily create a Foo object manually. In C++, it's not so bad:
FooPtr foo(new Foo());
bar->useFoo(foo);
But in C#, this requires:
FooPtr foo = new FooPtr(new Foo());
bar.useFoo(foo);
Even if I did some fancy renaming, it would be:
Foo foo = new Foo(new FooImpl());
bar.useFoo(foo);
That whole double-new thing really is ugly and cumbersome. And it also
introduces some memory management issues. C# will try and delete the
Foo object, even though the pointer is now owned by FooPtr, and I get a
double-free at some point.
I have complete control over the Foo and Bar APIs and I'm willing to
make changes to make this more SWIG-able. I still want to use
shared_ptr as it greatly simplifies memory management. Has anyone else
come across this issue and if so, what was their solutions?
The only solution I've come up with so far is to not expose shared_ptr
objects to end users by doing a PIMPL implementation, with the private
implementation pointer being a shared_ptr. This works beautifully, and
is easily SWIG-able. But it's somewhat of a pain to maintain because
the main and Impl class have common methods that need to be repeated.
In the interest of the Don't Repeat Yourself (DRY) concept, I'd like to
avoid that. But barring any other suggestions, the PIMPL route is the
way I'm going to go. It works for SWIG and yet keeps C++ memory
management sane and exception safe.
-Dave
_______________________________________________
Swig maillist - ***@cs.uchicago.edu
http://mailman.cs.uchicago.edu/mailman/listinfo/swig