我想使用protobuf,特别是python的cpp生成代码实现。 到目前为止,我已经在cpp中使用静态链接构建了protobuf3.7,并使用cpp_implementation安装了python版本,该版本使用了cpp-reflection实现。
下一步的起点是:Fast, native-C Protocol Buffers from Python,它适用于python2。 我最终跟随this guide on how to write cpython extension modules using C++,并尝试模拟对the benchmarks of protobuf. https://github.com/protocolbuffers/protobuf/blob/master/benchmarks/python/py_benchmark.py所做的工作,并为其编写一个 setup.py :
from distutils.core import setup, Extension
module1 = Extension('podpb',
include_dirs = ['C:\mydir\podpb\include'],
libraries = ['libprotobuf', 'my_other_lib_static'],
library_dirs = ['C:\mydir\podpb\lib',
'C:\mydir\otherlib\install\lib'],
sources = ['podpb.cpp'],
extra_compile_args = ['/MT'],
language='c++'
#extra_link_args = ['-static']
)
setup (name = 'ProtobufC',
version = '0.1',
packages = ['podpb'],
#cmdclass = {'build_ext': build_ext},
description = 'PB as a C module',
ext_modules = [module1])
podpb.cpp:
#include <Python.h>
#include "my_headers.pb.h"
...
static PyMethodDef PodMethods[] = {
{NULL, NULL, 0, NULL} /* Sentinel */
};
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"podpb", /* m_name */
"This is a module", /* m_doc */
-1, /* m_size */
PodMethods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
PyMODINIT_FUNC
PyInit_podpb(void)
{
my_namespace::my_class().descriptor();
...
PyObject* m = PyModule_Create(&moduledef);
return m;
}
我现在有一个podpb.cp36-win_amd64.pyd和一个ProtobufC-0.1-py3.6.egg-info文件,并试图通过简单地将其导入来使用它like this(在我的情况下是导入podpb ,请在例如)中导入libbenchmark_messages。在示例中,除了导入之外,根本不使用它。
[更新@ 2019/03/25] 我使用line_profiler来衡量性能,从cpp-reflection到cpp生成的代码时,我看不到任何改进。这是基准脚本:
import os
import podpb
def my_function(version):
some_path = 'something3' if (version == 3) else 'something'
this_path = os.path.dirname(os.path.realpath(__file__))
data_path = os.path.join(this_path, '..', 'data', some_path)
some_files = [x for x in os.listdir(data_path) if x.endswith('.bin')]
skey = lambda x : int(x.split('.')[0].split('_')[1])
some_packages = []
for fname in sorted(some_files, key=skey):
with open(os.path.join(data_path, fname), 'rb') as f:
some_packages.append(b"".join(f.readlines()))
return some_packages
@profile
def main():
from some3.place import SomeData as Data3
some_files = my_function(3)
o = Data3()
N = 1000
for i, some_msg in enumerate(some_files [:N]):
o.ParseFromString(some_msg)
print(i)
if __name__=='__main__':
main()
我正确使用了吗?
[/ update]