如何为python3使用protobuf的cpp生成代码实现?

时间:2019-03-20 08:20:15

标签: c++ python-3.x protocol-buffers

我想使用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]

0 个答案:

没有答案