{"action":"created","issue":{"url":"https://api.github.com/repos/google/flatbuffers/issues/4969","repository_url":"https://api.github.com/repos/google/flatbuffers","labels_url":"https://api.github.com/repos/google/flatbuffers/issues/4969/labels{/name}","comments_url":"https://api.github.com/repos/google/flatbuffers/issues/4969/comments","events_url":"https://api.github.com/repos/google/flatbuffers/issues/4969/events","html_url":"https://github.com/google/flatbuffers/issues/4969","id":366849842,"node_id":"MDU6SXNzdWUzNjY4NDk4NDI=","number":4969,"title":"native_type for tables in c++ object based api","user":{"login":"buster3","id":6793480,"node_id":"MDQ6VXNlcjY3OTM0ODA=","avatar_url":"https://avatars3.githubusercontent.com/u/6793480?v=4","gravatar_id":"","url":"https://api.github.com/users/buster3","html_url":"https://github.com/buster3","followers_url":"https://api.github.com/users/buster3/followers","following_url":"https://api.github.com/users/buster3/following{/other_user}","gists_url":"https://api.github.com/users/buster3/gists{/gist_id}","starred_url":"https://api.github.com/users/buster3/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/buster3/subscriptions","organizations_url":"https://api.github.com/users/buster3/orgs","repos_url":"https://api.github.com/users/buster3/repos","events_url":"https://api.github.com/users/buster3/events{/privacy}","received_events_url":"https://api.github.com/users/buster3/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":4,"created_at":"2018-10-04T15:35:54Z","updated_at":"2018-10-10T13:33:43Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"Hi everybody,\r\nI like to use custom types for tables in the object based API. The behavior should be equal to the \"native_type\" attribute for structs. I hope to get some feedback on the idea and possible pack and unpack APIs.\r\n\r\nExample:\r\n```\r\ntable MatrixXd (native_type:\"Eigen::MatrixXd\") {\r\n  rows:uint32;\r\n  data:[double];\r\n}\r\n\r\ntable Signal {\r\n  mat:MatrixXd;\r\n}\r\n```\r\n\r\nI like to get an object API similar to:\r\n```\r\nstruct SignalT {\r\n  Eigen::MatrixXd mat; // instead of std::unique_ptr<MatrixXdT>mat;\r\n}\r\n```\r\n\r\nFor structs the user has to specify the following functions:\r\n```\r\nnamespace flatbuffers { \r\nnative_type UnPack(const FlatbufferStruct& obj); \r\nFlatbufferStruct Pack(const native_type& obj); \r\n}\r\n```\r\nI think this is no suitable interface for tables, as \"Pack\" should directly map to a FlatBufferBuilder.\r\n\r\n**UnPack**\r\ndefault is ` { auto _e = mat(); if (_e) _o->mat = std::unique_ptr<MatrixXdT>(_e->UnPack(_resolver)); };`\r\nThe actual unpack functionality is implemented in \"UnPackTo\". Both UnPack and UnPackTo are members of the generated code and thus can not be user defined. I would suggest:\r\n\r\n`native_type UnPack(const FlatbufferTable& obj, const flatbuffers::resolver_function_t *_resolver = nullptr); \r\n` or alternatively  \r\n`void UnPackTo(native_type *_o, const FlatbufferTable& obj, const flatbuffers::resolver_function_t *_resolver = nullptr); `\r\nI would prefer the first version. Return value optimization should do it's job.\r\n\r\n**Pack**\r\nThere is a \"Pack\" method generated for each Table. On the other hand there are two overloaded CreateType functions which do the actual work. I think the interface is similar to what we like to have.\r\n\r\nSuggestion:\r\n`inline flatbuffers::Offset<Signal> CreateSignal(flatbuffers::FlatBufferBuilder &_fbb, const native_type &_o, const flatbuffers::rehasher_function_t *_rehasher);`\r\n\r\nI think it is possible to clean up the various generated code pack and unpack functions. For compatibility reasons we should not do so? I am looking forward to some feedback.\r\n\r\nBest regards\r\nThomas"},"comment":{"url":"https://api.github.com/repos/google/flatbuffers/issues/comments/428573095","html_url":"https://github.com/google/flatbuffers/issues/4969#issuecomment-428573095","issue_url":"https://api.github.com/repos/google/flatbuffers/issues/4969","id":428573095,"node_id":"MDEyOklzc3VlQ29tbWVudDQyODU3MzA5NQ==","user":{"login":"buster3","id":6793480,"node_id":"MDQ6VXNlcjY3OTM0ODA=","avatar_url":"https://avatars3.githubusercontent.com/u/6793480?v=4","gravatar_id":"","url":"https://api.github.com/users/buster3","html_url":"https://github.com/buster3","followers_url":"https://api.github.com/users/buster3/followers","following_url":"https://api.github.com/users/buster3/following{/other_user}","gists_url":"https://api.github.com/users/buster3/gists{/gist_id}","starred_url":"https://api.github.com/users/buster3/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/buster3/subscriptions","organizations_url":"https://api.github.com/users/buster3/orgs","repos_url":"https://api.github.com/users/buster3/repos","events_url":"https://api.github.com/users/buster3/events{/privacy}","received_events_url":"https://api.github.com/users/buster3/received_events","type":"User","site_admin":false},"created_at":"2018-10-10T13:33:43Z","updated_at":"2018-10-10T13:33:43Z","author_association":"CONTRIBUTOR","body":"- Ok, got it. Table values can be null.\r\n- You are right. If i predefine prototypes `Pack` works. Additionally, I have to make a forward declaration for the generated classes. All in all it looks quite messy. Example:\r\n```\r\n#pragma once\r\n#include <complex>\r\n\r\n// forward declaration of generated classes\r\nstruct Complex;\r\n\r\nnamespace flatbuffers {\r\n    Complex Pack(const std::complex<double>& obj);\r\n    std::complex<double> UnPack(const Complex& obj);\r\n}\r\n\r\n#include \"test_generated.h\"\r\n\r\nnamespace flatbuffers {\r\n    inline Complex Pack(const std::complex<double>& obj)\r\n    {\r\n        return Complex(obj.real(), obj.imag());\r\n    }\r\n\r\n    inline std::complex<double> UnPack(const Complex& obj)\r\n    {\r\n        return std::complex<double>(obj.i(), obj.q());\r\n    }\r\n}\r\n```\r\nIt might have been a good idea to split the object base API in a separate header.\r\n\r\n- I think the following definition does not produce compilable code. `std::complex<double>` can not be converted to `std::unique_ptr<std::complex<double>>`.\r\n```\r\nstruct Complex (native_type:\"std::complex<double>\") {\r\n  i:double;\r\n  q:double;\r\n}\r\n\r\ntable FooConfig {\r\n  native_inline:Complex (native_inline);\r\n  default:Complex;\r\n}\r\n```\r\n\r\n**Native_type for tables**\r\nI make the following suggestion:\r\n- Automatically `native_inline` all structs/tables with a `native_type`. Users who wants to have a `std::unique_ptr<User_t>` can define `(native_type:\"std::unique_ptr<User_t>\")`. \r\n- `inline flatbuffers::Offset<Signal> Pack(flatbuffers::FlatBufferBuilder &_fbb, const native_type &_o, const flatbuffers::rehasher_function_t *_rehasher);`\r\n- `native_type UnPack(const FlatbufferTable& obj, const flatbuffers::resolver_function_t *_resolver = nullptr);`"}}
{"actor":{"display_login":"buster3"}}