using mojo structs in implementations?

20 views
Skip to first unread message

Tim Steele

unread,
Jun 23, 2014, 3:14:53 PM6/23/14
to mojo...@chromium.org
Looking at examples in the code, a common scenario with mojo structs is to convert to/from an app-defined data structure.  type_converter.h mentions mojo::geometry::Point <> gfx::Point as an example.

Sometimes there is no pre-existing app defined data structure like gfx::Point. Are mojo structs intended to be also used as the data structures in real implementations, or was the idea they be mainly used for "over the wire" mojo messages?  

I ask because I was finding it less-than-obvious how to take MyStructPtr (or, a mojo::Array<MyStructPtr>) passed to a function I'm implementing in my InterfaceImpl and then stash a copy of the structs in my class.  At least, I was expecting behaviour similar to protobufs, where this mostly "just works". Most of the examples I've seen in mojo convert to an app defined type and then use those inside std::vector, or something like that.

Tim

Darin Fisher

unread,
Jun 23, 2014, 4:01:27 PM6/23/14
to Tim Steele, mojo...@chromium.org

The generated classes are suitable for using anyhow you see fit in your code. They do not need to be used exclusively with mojom method calls.

Tim Steele

unread,
Jun 23, 2014, 4:43:07 PM6/23/14
to Darin Fisher, mojo...@chromium.org
Oh. I must be misunderstanding something :(  Say we have

module mojo.foo {

struct Foo {
  string name;
  uint8 id;
}

}  // mojo.foo

For this, a typedef mojo::InlinedStructPtr<Foo> FooPtr will be generated.  InlinedStructPtr has a comment, "// Designed to be used when Struct is small and copyable." but it's actually move-only as far as I can tell. How is that supposed to work?

James Robinson

unread,
Jun 23, 2014, 4:48:04 PM6/23/14
to Tim Steele, Darin Fisher, mojo...@chromium.org
The generated class for mojo/services/public/interfaces/geometry/geometry.mojom's Point type, defined as:

struct Point {
  int32 x;
  int32 y;
};

is:

class Point {
 public:
  typedef internal::Point_Data Data_;
  static PointPtr New();

  template <typename U>
  static PointPtr From(const U& u) {
    return mojo::TypeConverter<PointPtr, U>::ConvertFrom(u);
  }

  Point();
  ~Point();

  int32_t x;
  int32_t y;
};

You can use mojo::Point in your code if you want.  I'd imagine you'd have a mojo::foo::Foo in your example with a similar structure.  I think if I was writing code using these I'd mostly ignore the Ptr types and just use them as POD structs.

- James

Tim Steele

unread,
Jun 23, 2014, 5:19:39 PM6/23/14
to James Robinson, Darin Fisher, mojo...@chromium.org
That makes sense. I guess the main issue I'm having is that the Ptr types handed to you in a mojom method implementation aren't copyable (although the comments in struct_ptr.h kind of imply otherwise, so I thought maybe I was missing something?).  So if you have something like

interface MyService {
  Save(Point point)
  SavePoints(Point[] points)  
}

you end up implementing a function like 'void SavePoints(mojo::Array<PointPtr> points)' and having to write the code to iterate and .Pass() one by one to an array or std::vector of your own.

Ben Goodger (Google)

unread,
Jun 23, 2014, 5:24:52 PM6/23/14
to Tim Steele, James Robinson, Darin Fisher, mojo...@chromium.org
I am suspicious that these types will be that useful in client code for many of the reasons cited.

-Ben

Yuzhu Shen

unread,
Jun 23, 2014, 5:29:13 PM6/23/14
to Tim Steele, James Robinson, Darin Fisher, mojo...@chromium.org
On Mon, Jun 23, 2014 at 2:19 PM, 'Tim Steele' via mojo-dev <mojo...@chromium.org> wrote:
That makes sense. I guess the main issue I'm having is that the Ptr types handed to you in a mojom method implementation aren't copyable (although the comments in struct_ptr.h kind of imply otherwise,

The comment doesn't mean that mojo::InlinedStructPtr<Foo> is copyable. Instead, it says that using mojo::InlinedStructPtr<Foo> requires that Foo to be copyable. (Because we use std::swap() with Foo, I think.)

Darin Fisher

unread,
Jun 23, 2014, 7:13:59 PM6/23/14
to Yuzhu Shen, Tim Steele, James Robinson, mojo...@chromium.org
On Mon, Jun 23, 2014 at 2:29 PM, Yuzhu Shen <yzs...@chromium.org> wrote:



On Mon, Jun 23, 2014 at 2:19 PM, 'Tim Steele' via mojo-dev <mojo...@chromium.org> wrote:
That makes sense. I guess the main issue I'm having is that the Ptr types handed to you in a mojom method implementation aren't copyable (although the comments in struct_ptr.h kind of imply otherwise,

The comment doesn't mean that mojo::InlinedStructPtr<Foo> is copyable. Instead, it says that using mojo::InlinedStructPtr<Foo> requires that Foo to be copyable. (Because we use std::swap() with Foo, I think.)

Right. InlinedStructPtr<T> is just an optimization for small POD T. It avoids a heap allocation as compared to StructPtr<T>. You really shouldn't need to worry too much about it.

-Darin

James Robinson

unread,
Jun 24, 2014, 9:07:02 PM6/24/14
to Tim Steele, Darin Fisher, mojo...@chromium.org
On Mon, Jun 23, 2014 at 2:19 PM, Tim Steele <tims...@google.com> wrote:
That makes sense. I guess the main issue I'm having is that the Ptr types handed to you in a mojom method implementation aren't copyable (although the comments in struct_ptr.h kind of imply otherwise, so I thought maybe I was missing something?).  So if you have something like

interface MyService {
  Save(Point point)
  SavePoints(Point[] points)  
}

you end up implementing a function like 'void SavePoints(mojo::Array<PointPtr> points)' and having to write the code to iterate and .Pass() one by one to an array or std::vector of your own.

This is a slight aside, but in a situation similar to this where I had this sort of mojom and needed to interface with chromium code expecting a std::vector<chromium::Point>, I found it useful to write type converters for the mojo::Array types, i.e.

namespace mojo {
template <>
class TypeConverter<Array<PointPtr> >, std::vector<chromium::Point>> {
 public:
  static Array<PointPtr> ConvertTo(const std::vector<chromium::Point>& input);
  static std::vector<chromium::Point> ConvertTo(const Array<PointPtr>& input);
}
}



and then using your TypeConverter<PointPtr, chromium::Point> to keep the implementation simple.  You still have to write the code to iterate and .Pass(), but you only have to do it once for the type of array instead of having to do all over the place.  This might be obvious, but it wasn't clear to me at first that the type converter system would make this somewhat straightforward.
Reply all
Reply to author
Forward
0 new messages