Suggestions for handling std::unique_ptr/std::shared_ptr?

275 views
Skip to first unread message

Bob Ziuchkovski

unread,
Oct 31, 2012, 6:34:53 PM10/31/12
to javacpp...@googlegroups.com
Hi,

I'm working with a library that returns smart pointers to objects via
std::unique_ptr and std::shared_ptr. Thus far I have been defining
additional JavaCPP wrapper classes for each smart pointer template type.
However, I am struggling with both the amount of extra code repetition
for each object type, as well as deallocator interaction. For the
latter problem, I have to store references to both the smart pointer and
its pointed-to object, or else the deallocator calls the smart pointer
destructor while I'm still using the pointed-to object. This has been
particularly troublesome when I need to cast the pointed-to type to a
different type (i.e. cast to different wrapped JavaCPP object via
Constructor(Pointer p)), as passing around the original smart pointer
becomes an even greater mess.

Anyway, I'm looking for advice on how to better handle smart pointers
with JavaCPP. There might be functionality within JavaCPP that I'm
currently missing. Or, perhaps JavaCPP could use a feature enhancement
to better tackle the problem?

I'm open to any advice at all. =)

Bob

Samuel Audet

unread,
Oct 31, 2012, 9:59:49 PM10/31/12
to javacpp...@googlegroups.com
On 11/01/2012 07:34 AM, Bob Ziuchkovski wrote:
> I'm working with a library that returns smart pointers to objects via
> std::unique_ptr and std::shared_ptr. Thus far I have been defining
> additional JavaCPP wrapper classes for each smart pointer template type.
> However, I am struggling with both the amount of extra code repetition
> for each object type, as well as deallocator interaction. For the
> latter problem, I have to store references to both the smart pointer and
> its pointed-to object, or else the deallocator calls the smart pointer
> destructor while I'm still using the pointed-to object. This has been
> particularly troublesome when I need to cast the pointed-to type to a
> different type (i.e. cast to different wrapped JavaCPP object via
> Constructor(Pointer p)), as passing around the original smart pointer
> becomes an even greater mess.

Yep, it's a mess unfortunately...

> Anyway, I'm looking for advice on how to better handle smart pointers
> with JavaCPP. There might be functionality within JavaCPP that I'm

Well, let's see, one thing we could do is never ever access the wrapped
object, and always call get() on the smart pointer. Or actually, we
could cache the result on construction and put the result in an "obj"
field or something?

Or here's another way of doing it maybe. We could
@Name("shared_ptr<...>)") the main Pointer class. allocate() won't work
on it, but the fields and operators should work, right? Then the only
two or three things we might want is a create() factory method of some
sort, but that's usually provided by the library, a deallocator that we
could register, and a get() method to return the underlying real
pointer, which we could make @Opaque to keep it type safe, but not have
it used by users to access the fields. How does that sound?

> currently missing. Or, perhaps JavaCPP could use a feature enhancement
> to better tackle the problem?

I'm opened to suggestions!

> I'm open to any advice at all. =)

me too :)

Samuel

Bob Ziuchkovski

unread,
Nov 1, 2012, 1:45:08 AM11/1/12
to javacpp...@googlegroups.com
Thanks for the ideas. I think my ideal case would be to use an adapter
to manage the pointer access, but I'm not entirely sure how the
specifics would work. Here's an example of what I'm thinking...

Let's say we have a contrived event service that looks something like
the following in C++:



class EventService {
public:
std::shared_ptr<Event> getNextEvent();
};

class Event {
public:
int getType();
};

class StringEvent : public Event {
std::string getString();
};



I would love to define it on the JavaCPP side as follows:



@Name("EventService")
public static class EventService extends Pointer {
public native @Adapter("SharedPointerAdapter<Event>") Event
getNextEvent();
}

@Name("Event")
public static class Event extends Pointer {
public native int getType();
}

@Name("StringEvent")
public static class StringEvent extends Pointer {
public StringEvent(Pointer p) {
super(p);
}

public native String getString();
}



And code that would use the above:



EventService service = new EventService();
Event event = service.getNextEvent();
if (event.getType() == 12345) {
StringEvent sev = new StringEvent(event);
System.out.println(sev.getString());
}



I see a similar use for a UniquePointerAdapter. In fact it would be
awesome if Adapters in general were an extensible concept. I know
VectorAdapter exists, but I could see registering adapter code snippets,
a la VectorAdapter.h, SharedPointerAdapter.h, UniquePointerAdapter.h,
etc. as well as project-specific Adapter snippets.

To making something work like the above example of casting Event to
StringEvent, I think Adapters would have to be instantiated on a
per-Pointer-object basis and copied alongside in Constructor(Pointer p),
but that doesn't seem too bad.

Oh well, I guess I'm probably dreaming a bit here. Anyway, for now I'll
explore some of the ideas you mentioned. The extensible Adapter idea is
definitely a wish-list item I'd vote for though. =)

Thanks again for the input!

Bob

Samuel Audet

unread,
Nov 1, 2012, 9:14:57 AM11/1/12
to javacpp...@googlegroups.com
Hello,

Yes, you can create your own adapters, like this in JavaCV:
http://code.google.com/p/javacv/source/browse/src/main/resources/com/googlecode/javacv/cpp/opencv_adapters.h

That's not the problem. The problem is that we need to keep a reference
to the smart pointer, while the adapter only exists the time of the
function call.

I guess it would be possible to deconstruct a shared_ptr to get() the
pointer and get_deleter(), and stuff that into a Pointer object...
Interesting. Let me know if it works!

Samuel Audet

unread,
Nov 3, 2012, 1:29:15 AM11/3/12
to javacpp...@googlegroups.com
Actually, I've just made one for cv::Ptr here:
http://code.google.com/p/javacv/source/browse/src/main/resources/com/googlecode/javacv/cpp/opencv_adapters.h#190
It should be possible to write something pretty similar for unique_ptr
and shared_ptr as well.

Since the idea with this here is to use Java's garbage collection, this
is really only safe if the pointer never ends up being saved anywhere in
native code...

Samuel
Reply all
Reply to author
Forward
0 new messages