c# - 如何为C++、protobuf制作swig接口(interface)文件

标签 c# c++ protocol-buffers swig

显然,protobuf 需要知道涉及的所有 header 。

下面是Header.h的内容

Test.h是protobuf生成的头文件

#pragma once
#include "Test.h"

class TestClass
{
private:
    test::Person _person;
public:
    bool eventReceiveData(char*);
    bool eventRecieveData(char* const);
    bool eventRecieveData(std::string);
    std::string getData() const;

    void eventReceiveMessage(test::Person);
    test::Person getPerson();
};

由于 Test.h 包含所有这些头文件,

#include <google/protobuf/stubs/common.h

#include <google/protobuf/arena.h>
#include <google/protobuf/arenastring.h>
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/metadata.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/unknown_field_set.h>

这是否意味着我必须这样做?

%module Test
%{
#include "Header.h"
%}
%include "Header.h"
%include <google/protobuf/stubs/common.h>
%include <google/protobuf/arena.h>
%include <google/protobuf/arenastring.h>
%include <google/protobuf/generated_message_util.h>
%include <google/protobuf/metadata.h>
%include <google/protobuf/message.h>
%include <google/protobuf/repeated_field.h>
%include <google/protobuf/extension_set.h>
%include <google/protobuf/unknown_field_set.h>

而且,我是否必须包含 protobuf 的所有静态库?

我的目标语言是 C#

关于同时使用 swig 和 protobuf 的信息太少了。

最佳答案

基于您的 protobuf 对象有一个命名空间这一事实,我假设您使用的是普通的 C++ 协议(protocol)。

对您问题的简短回答是,不,您不必在 SWIG 接口(interface)中包含所有或任何 protobuf header 。不过,您可能希望在 SWIG 中包含一些或增强/替换它们,以使其真正完全、整齐地工作。我将向您展示如何做到这一点,但我坚信这对于大多数情况来说不是正确的设计解决方案。请参阅本答案末尾我建议的替代方案。

作为讨论的示例,我从 protobuf 教程中获取了 person.proto。我认为这也是您正在处理的问题,但这很难说,所以这里是:

message Person {
  required int32 id = 1;
  required string name = 2;
  optional string email = 3;
}

当我们运行 protoc 时,我们会得到一个 .h 文件。如果我们从 SWIG 界面开始,例如:

%module test
%{
#include "person.pb.h"
%}
%include "person.pb.h"

然后我们生成了一个几乎无法使用的 C# 接口(interface) - SWIG 没有整齐地包装 std::string 或 Google 的 ::google::protobuf::int32 类型,因为它对它们一无所知。

另一方面,如果我们编写一个 protobuf.i 文件:

%include <std_string.i>
%include <stdint.i>
#define GOOGLE_PROTOBUF_VERSION 2006001
#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 2006001
namespace google {
namespace protobuf {
typedef int32 int32_t;
typedef uint8 uint8_t;
// ... whatever else you need
}
}

并在您的模块中使用它:

%module test
%include "protobuf.i"
%{
#include "person.pb.h"
%}
%include "person.pb.h"

那么现在我们开始做生意了,这是在包装界面中获得正常功能所需的最低限度。您将能够使用 C++ 在 C++ 中为您创建和管理的 protobuf 对象,并具有“beanlike”行为,即基本的集合和获取将可用。

有很多东西如果不做更多的工作就无法使用,例如描述符、元数据、消息类型、编码 io、具有所有权转移的字符串。

这些问题都可以通过在 SWIG 界面中做更多工作来修复,但我认为您从错误的角度解决了这个问题。您已经有一个适用于 C# 和 C++ 的 protobuf 编译器,所以我要做的就是添加一个 setPerson() 以及一个 getPerson() 方法,使用 SWIG 中的输入和输出类型映射来透明地序列化和构造 native C++/C# 对应类型。这是一个特别好的计划,因为您的 getPerson() 方法故意或以其他方式返回的是私有(private)成员的拷贝而不是引用,因此更改返回的底层 protobuf 对象不会有任何可见的结果无论如何,在 C++ 中都会有效果。

关于c# - 如何为C++、protobuf制作swig接口(interface)文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41849910/

相关文章:

c# - LINQ - 字典中的字典

c# - 查找当前时间是否落在多个时间范围之间

c++ - emacs:在另一个实例中自动打开相应的文件

linux - 强制QT使用系统protobuf版本

c++ - 关于 Google 的 protobuf

c# - Visual Studio 2010 (C#) 中 ReportDocument 的 SetDataSource 错误

c# - 非 Linq 检查列表项的方法是相同的

c++ - 将 vector<double> 插入 vector<vector<double>>

c++ - Ubuntu : undefined reference to `al_install_system' 中的快板

java.lang.IndexOutOfBoundsException - 使用 Protocol buffer 构建 Java 对象时