@@ -158,54 +158,103 @@ google::protobuf::DynamicMessageFactory* GetFactory() {
158
158
return factory;
159
159
}
160
160
161
+ absl::StatusOr<google::protobuf::Message*> CreateNewMessage (PyObject* py_msg) {
162
+ PyObject* pyd = PyObject_GetAttrString (py_msg, " DESCRIPTOR" );
163
+ if (pyd == nullptr ) {
164
+ return absl::InvalidArgumentError (" py_msg has no attribute 'DESCRIPTOR'" );
165
+ }
166
+
167
+ PyObject* fn = PyObject_GetAttrString (pyd, " full_name" );
168
+ if (fn == nullptr ) {
169
+ return absl::InvalidArgumentError (
170
+ " DESCRIPTOR has no attribute 'full_name'" );
171
+ }
172
+
173
+ const char * descriptor_full_name = PyUnicode_AsUTF8 (fn);
174
+ if (descriptor_full_name == nullptr ) {
175
+ return absl::InternalError (" Fail to convert descriptor full name" );
176
+ }
177
+
178
+ PyObject* pyfile = PyObject_GetAttrString (pyd, " file" );
179
+ Py_DECREF (pyd);
180
+ if (pyfile == nullptr ) {
181
+ return absl::InvalidArgumentError (" DESCRIPTOR has no attribute 'file'" );
182
+ }
183
+ auto gen_d = google::protobuf::DescriptorPool::generated_pool ()->FindMessageTypeByName (
184
+ descriptor_full_name);
185
+ if (gen_d) {
186
+ Py_DECREF (pyfile);
187
+ Py_DECREF (fn);
188
+ return google::protobuf::MessageFactory::generated_factory ()
189
+ ->GetPrototype (gen_d)
190
+ ->New ();
191
+ }
192
+ auto d = FindMessageDescriptor (pyfile, descriptor_full_name);
193
+ Py_DECREF (pyfile);
194
+ RETURN_IF_ERROR (d.status ());
195
+ Py_DECREF (fn);
196
+ return GetFactory ()->GetPrototype (*d)->New ();
197
+ }
198
+
199
+ bool CopyToOwnedMsg (google::protobuf::Message** copy, const google::protobuf::Message& message) {
200
+ *copy = message.New ();
201
+ std::string wire;
202
+ message.SerializeToString (&wire);
203
+ (*copy)->ParseFromArray (wire.data (), wire.size ());
204
+ return true ;
205
+ }
206
+
161
207
// C++ API. Clients get at this via proto_api.h
162
208
struct ApiImplementation : google::protobuf::python::PyProto_API {
163
209
absl::StatusOr<google::protobuf::python::PythonMessageMutator> GetClearedMessageMutator (
164
210
PyObject* py_msg) const override {
165
211
if (PyObject_TypeCheck (py_msg, google::protobuf::python::CMessage_Type)) {
166
212
google::protobuf::Message* message =
167
213
google::protobuf::python::PyMessage_GetMutableMessagePointer (py_msg);
214
+ if (message == nullptr ) {
215
+ return absl::InternalError (
216
+ " Fail to get message pointer. The message "
217
+ " may already had a reference." );
218
+ }
168
219
message->Clear ();
169
220
return CreatePythonMessageMutator (nullptr , message, py_msg);
170
221
}
171
- PyObject* pyd = PyObject_GetAttrString (py_msg, " DESCRIPTOR" );
172
- if (pyd == nullptr ) {
173
- return absl::InvalidArgumentError (" py_msg has no attribute 'DESCRIPTOR'" );
174
- }
175
222
176
- PyObject* fn = PyObject_GetAttrString (pyd, " full_name" );
177
- if (fn == nullptr ) {
178
- return absl::InvalidArgumentError (
179
- " DESCRIPTOR has no attribute 'full_name'" );
180
- }
223
+ auto msg = CreateNewMessage (py_msg);
224
+ RETURN_IF_ERROR (msg.status ());
225
+ return CreatePythonMessageMutator (*msg, *msg, py_msg);
226
+ }
181
227
182
- const char * descriptor_full_name = PyUnicode_AsUTF8 (fn);
183
- if (descriptor_full_name == nullptr ) {
184
- return absl::InternalError (" Fail to convert descriptor full name" );
228
+ absl::StatusOr<google::protobuf::python::PythonConstMessagePointer>
229
+ GetConstMessagePointer (PyObject* py_msg) const override {
230
+ if (PyObject_TypeCheck (py_msg, google::protobuf::python::CMessage_Type)) {
231
+ const google::protobuf::Message* message =
232
+ google::protobuf::python::PyMessage_GetMessagePointer (py_msg);
233
+ google::protobuf::Message* owned_msg = nullptr ;
234
+ ABSL_DCHECK (CopyToOwnedMsg (&owned_msg, *message));
235
+ return CreatePythonConstMessagePointer (owned_msg, message, py_msg);
185
236
}
186
-
187
- PyObject* pyfile = PyObject_GetAttrString (pyd, " file" );
188
- Py_DECREF (pyd);
189
- if (pyfile == nullptr ) {
190
- return absl::InvalidArgumentError (" DESCRIPTOR has no attribute 'file'" );
237
+ auto msg = CreateNewMessage (py_msg);
238
+ RETURN_IF_ERROR (msg.status ());
239
+ PyObject* serialized_pb (
240
+ PyObject_CallMethod (py_msg, " SerializeToString" , nullptr ));
241
+ if (serialized_pb == nullptr ) {
242
+ return absl::InternalError (" Fail to serialize py_msg" );
191
243
}
192
- auto gen_d =
193
- google::protobuf::DescriptorPool::generated_pool ()->FindMessageTypeByName (
194
- descriptor_full_name);
195
- if (gen_d) {
196
- Py_DECREF (pyfile);
197
- Py_DECREF (fn);
198
- google::protobuf::Message* msg = google::protobuf::MessageFactory::generated_factory ()
199
- ->GetPrototype (gen_d)
200
- ->New ();
201
- return CreatePythonMessageMutator (msg, msg, py_msg);
244
+ char * data;
245
+ Py_ssize_t len;
246
+ if (PyBytes_AsStringAndSize (serialized_pb, &data, &len) < 0 ) {
247
+ Py_DECREF (serialized_pb);
248
+ return absl::InternalError (
249
+ " Fail to get bytes from py_msg serialized data" );
202
250
}
203
- auto d = FindMessageDescriptor (pyfile, descriptor_full_name);
204
- Py_DECREF (pyfile);
205
- RETURN_IF_ERROR (d.status ());
206
- Py_DECREF (fn);
207
- google::protobuf::Message* msg = GetFactory ()->GetPrototype (*d)->New ();
208
- return CreatePythonMessageMutator (msg, msg, py_msg);
251
+ if (!(*msg)->ParseFromArray (data, len)) {
252
+ Py_DECREF (serialized_pb);
253
+ return absl::InternalError (
254
+ " Couldn't parse py_message to google::protobuf::Message*!" );
255
+ }
256
+ Py_DECREF (serialized_pb);
257
+ return CreatePythonConstMessagePointer (*msg, *msg, py_msg);
209
258
}
210
259
211
260
const google::protobuf::Message* GetMessagePointer (PyObject* msg) const override {
0 commit comments