Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
P
protobuf
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
protobuf
Commits
a7252bf4
Unverified
Commit
a7252bf4
authored
Jun 03, 2018
by
Feng Xiao
Committed by
GitHub
Jun 03, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #4698 from ThomasColthurst/proto_c_api
Introduce Proto C API; based on cl/198113115 by amauryfa
parents
17ab85de
7c651424
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
148 additions
and
1 deletion
+148
-1
BUILD
BUILD
+10
-0
Makefile.am
Makefile.am
+1
-0
proto_api.h
python/google/protobuf/proto_api.h
+92
-0
message.cc
python/google/protobuf/pyext/message.cc
+25
-1
message.h
python/google/protobuf/pyext/message.h
+3
-0
message_module.cc
python/google/protobuf/pyext/message_module.cc
+17
-0
No files found.
BUILD
View file @
a7252bf4
...
...
@@ -671,6 +671,7 @@ cc_binary(
linkstatic = 1,
deps = [
":protobuf",
":proto_api",
] + select({
"//conditions:default": [],
":use_fast_cpp_protos": ["//external:python_headers"],
...
...
@@ -813,6 +814,15 @@ internal_protobuf_py_tests(
deps = [":python_tests"],
)
cc_library(
name = "proto_api",
hdrs = ["python/google/protobuf/proto_api.h"],
deps = [
":protobuf_python",
"//external:python_headers",
],
)
proto_lang_toolchain(
name = "cc_toolchain",
command_line = "--cpp_out=$(OUT)",
...
...
Makefile.am
View file @
a7252bf4
...
...
@@ -804,6 +804,7 @@ python_EXTRA_DIST= \
python/google/protobuf/message.py
\
python/google/protobuf/message_factory.py
\
python/google/protobuf/python_protobuf.h
\
python/google/protobuf/proto_api.h
\
python/google/protobuf/proto_builder.py
\
python/google/protobuf/pyext/README
\
python/google/protobuf/pyext/__init__.py
\
...
...
python/google/protobuf/proto_api.h
0 → 100644
View file @
a7252bf4
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This file can be included by other C++ libraries, typically extension modules
// which want to interact with the Python Messages coming from the "cpp"
// implementation of protocol buffers.
//
// Usage:
// Declare a (probably static) variable to hold the API:
// const PyProto_API* py_proto_api;
// In some initialization function, write:
// py_proto_api = static_cast<const PyProto_API*>(PyCapsule_Import(
// PyProtoAPICapsuleName(), 0));
// if (!py_proto_api) { ...handle ImportError... }
// Then use the methods of the returned class:
// py_proto_api->GetMessagePointer(...);
#ifndef PYTHON_GOOGLE_PROTOBUF_PROTO_API_H__
#define PYTHON_GOOGLE_PROTOBUF_PROTO_API_H__
#include <Python.h>
namespace
google
{
namespace
protobuf
{
class
Message
;
namespace
python
{
// Note on the implementation:
// This API is designed after
// https://docs.python.org/3/extending/extending.html#providing-a-c-api-for-an-extension-module
// The class below contains no mutable state, and all methods are "const";
// we use a C++ class instead of a C struct with functions pointers just because
// the code looks more readable.
struct
PyProto_API
{
// The API object is created at initialization time and never freed.
// This destructor is never called.
virtual
~
PyProto_API
()
{}
// Operations on Messages.
// If the passed object is a Python Message, returns its internal pointer.
// Otherwise, returns NULL with an exception set.
virtual
const
Message
*
GetMessagePointer
(
PyObject
*
msg
)
const
=
0
;
// If the passed object is a Python Message, returns a mutable pointer.
// Otherwise, returns NULL with an exception set.
// This function will succeed only if there are no other Python objects
// pointing to the message, like submessages or repeated containers.
// With the current implementation, only empty messages are in this case.
virtual
Message
*
GetMutableMessagePointer
(
PyObject
*
msg
)
const
=
0
;
};
inline
const
char
*
PyProtoAPICapsuleName
()
{
static
const
char
kCapsuleName
[]
=
"protobuf.python.google.protobuf.cpp._message.proto_API"
;
return
kCapsuleName
;
}
}
// namespace python
}
// namespace protobuf
}
// namespace google
#endif // PYTHON_GOOGLE_PROTOBUF_PROTO_API_H__
python/google/protobuf/pyext/message.cc
View file @
a7252bf4
...
...
@@ -2866,17 +2866,38 @@ const Message* (*GetCProtoInsidePyProtoPtr)(PyObject* msg);
Message
*
(
*
MutableCProtoInsidePyProtoPtr
)(
PyObject
*
msg
);
static
const
Message
*
GetCProtoInsidePyProtoImpl
(
PyObject
*
msg
)
{
const
Message
*
message
=
PyMessage_GetMessagePointer
(
msg
);
if
(
message
==
NULL
)
{
PyErr_Clear
();
return
NULL
;
}
return
message
;
}
static
Message
*
MutableCProtoInsidePyProtoImpl
(
PyObject
*
msg
)
{
Message
*
message
=
PyMessage_GetMutableMessagePointer
(
msg
);
if
(
message
==
NULL
)
{
PyErr_Clear
();
return
NULL
;
}
return
message
;
}
const
Message
*
PyMessage_GetMessagePointer
(
PyObject
*
msg
)
{
if
(
!
PyObject_TypeCheck
(
msg
,
&
CMessage_Type
))
{
PyErr_SetString
(
PyExc_TypeError
,
"Not a Message instance"
);
return
NULL
;
}
CMessage
*
cmsg
=
reinterpret_cast
<
CMessage
*>
(
msg
);
return
cmsg
->
message
;
}
static
Message
*
MutableCProtoInsidePyProtoImpl
(
PyObject
*
msg
)
{
Message
*
PyMessage_GetMutableMessagePointer
(
PyObject
*
msg
)
{
if
(
!
PyObject_TypeCheck
(
msg
,
&
CMessage_Type
))
{
PyErr_SetString
(
PyExc_TypeError
,
"Not a Message instance"
);
return
NULL
;
}
CMessage
*
cmsg
=
reinterpret_cast
<
CMessage
*>
(
msg
);
if
((
cmsg
->
composite_fields
&&
PyDict_Size
(
cmsg
->
composite_fields
)
!=
0
)
||
(
cmsg
->
extensions
!=
NULL
&&
...
...
@@ -2885,6 +2906,9 @@ static Message* MutableCProtoInsidePyProtoImpl(PyObject* msg) {
// the underlying C++ message back to the CMessage (e.g. removed repeated
// composite containers). We only allow direct mutation of the underlying
// C++ message if there is no child data in the CMessage.
PyErr_SetString
(
PyExc_ValueError
,
"Cannot reliably get a mutable pointer "
"to a message with extra references"
);
return
NULL
;
}
cmessage
::
AssureWritable
(
cmsg
);
...
...
python/google/protobuf/pyext/message.h
View file @
a7252bf4
...
...
@@ -341,6 +341,9 @@ bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor,
extern
PyObject
*
PickleError_class
;
const
Message
*
PyMessage_GetMessagePointer
(
PyObject
*
msg
);
Message
*
PyMessage_GetMutableMessagePointer
(
PyObject
*
msg
);
bool
InitProto2MessageModule
(
PyObject
*
m
);
#if LANG_CXX11
...
...
python/google/protobuf/pyext/message_module.cc
View file @
a7252bf4
...
...
@@ -31,9 +31,26 @@
#include <Python.h>
#include <google/protobuf/pyext/message.h>
#include <google/protobuf/proto_api.h>
#include <google/protobuf/message_lite.h>
namespace
{
// C++ API. Clients get at this via proto_api.h
struct
ApiImplementation
:
google
::
protobuf
::
python
::
PyProto_API
{
const
google
::
protobuf
::
Message
*
GetMessagePointer
(
PyObject
*
msg
)
const
override
{
return
google
::
protobuf
::
python
::
PyMessage_GetMessagePointer
(
msg
);
}
google
::
protobuf
::
Message
*
GetMutableMessagePointer
(
PyObject
*
msg
)
const
override
{
return
google
::
protobuf
::
python
::
PyMessage_GetMutableMessagePointer
(
msg
);
}
};
}
// namespace
static
PyObject
*
GetPythonProto3PreserveUnknownsDefault
(
PyObject
*
/*m*/
,
PyObject
*
/*args*/
)
{
if
(
google
::
protobuf
::
internal
::
GetProto3PreserveUnknownsDefault
())
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment