Rcpp 和 protobuf:Free 宏的双重定义
Rcpp and protobuf: double definition of Free macro
我正在开发一个 C++ 库并希望将其与 Python 和 R 接口。
核心思想是 R 和 Python 基本上 'empty shells' 用于绘图而不是其他,所有核心计算都是在 C++ 中完成的,因此接口只是一堆运行 相当于 C++ 'main' 和 return 输出到 R 或 Python 而不是将内容保存到文件的函数。
我的想法是以 server/client 方式使用 goolge 的协议缓冲区:数据使用序列化消息从 Python (R) 传递到 C++,然后在 C++ 中反序列化。计算在 C++ 中是 运行 并且 Python (R) 是 returned 一个 bytes/strings 的列表,每个列表对应于一个序列化的原型对象。
在 Python 中,由于 Pybind11,这就像一个魅力。
但是,在 R 中我得到一个奇怪的错误:
/usr/include/google/protobuf/arena_impl.h:174:60: error: macro "Free" passed 3 arguments, but takes just 1
void (*block_dealloc)(void*, size_t));
我认为这个问题是由于 Rcpp 定义了一个类似于 protobuf 的宏。
以下 MWE 重现了相同的错误。
这是折叠结构
.
├── src
│ ├── rcpp_exports.cpp
├── student.proto
└── test.R
在test.R
Rcpp::sourceCpp(file="src/rcpp_exports.cpp")
在rcpp_exports.cpp
#include <Rcpp.h>
using namespace Rcpp;
#include "student.pb.h"
// [[Rcpp::export]]
std::string foo() {
Student stud;
stud.set_grade(25);
return stud.DebugString();
}
在student.proto
syntax = "proto3";
message Student {
double grade = 1;
bool pass = 2;
}
然后使用
编译protobuf文件
> protoc --proto_path=. --cpp_out=./src student.proto
最后我 运行 test.R 文件
> Rscript test.R
获取以下错误日志:
In file included from /usr/include/google/protobuf/arena.h:55:0,
from /home/mario/dev/tesi/test_rproto/src/student.pb.h:24,
from rcpp_exports.cpp:3:
/usr/include/google/protobuf/arena_impl.h:174:60: error: macro "Free" passed 3 arguments, but takes just 1
void (*block_dealloc)(void*, size_t));
^
In file included from /usr/share/R/include/R.h:91:0,
from /home/mario/R/x86_64-pc-linux-gnu-library/3.6/Rcpp/include/Rcpp/r/headers.h:63,
from /home/mario/R/x86_64-pc-linux-gnu-library/3.6/Rcpp/include/RcppCommon.h:29,
from /home/mario/R/x86_64-pc-linux-gnu-library/3.6/Rcpp/include/Rcpp.h:27,
from rcpp_exports.cpp:1:
/usr/share/R/include/R_ext/RS.h:74:37: error: expected identifier before ‘(’ token
#define Free(p) (R_chk_free( (void *)(p) ), (p) = NULL)
^
/usr/share/R/include/R_ext/RS.h:74:47: error: ‘parameter’ declared as function returning a function
#define Free(p) (R_chk_free( (void *)(p) ), (p) = NULL)
^
/usr/share/R/include/R_ext/RS.h:74:50: error: expected ‘)’ before ‘,’ token
#define Free(p) (R_chk_free( (void *)(p) ), (p) = NULL)
^
make: *** [rcpp_exports.o] Error 1
我会推荐一些用于防御性编程的东西:
不要展平命名空间 即 删除 using namespace Rcpp;
并使用前缀显式调用您的函数。
通过在包含 Rcpp.h
或其他 R headers.[= 之前定义 #define STRICT_R_HEADERS
来要求严格包含(我们不能追溯为默认值) 17=]
在没有重新映射的情况下使用 R 函数,即 Rf_error()
通过定义 R_NO_REMAP
但 Rcpp 应该为您完成。
通过在包含的内容和方式上稍微自由一些,应该可以避免您在此处发现的冲突。
最后,我们在十多年前写了 RProtoBuf
(它实际上也参与了创建当前的 Rcpp
),但我 从未 收到了您在此处收到的错误消息。所以明明是可以避免的。
我正在开发一个 C++ 库并希望将其与 Python 和 R 接口。
核心思想是 R 和 Python 基本上 'empty shells' 用于绘图而不是其他,所有核心计算都是在 C++ 中完成的,因此接口只是一堆运行 相当于 C++ 'main' 和 return 输出到 R 或 Python 而不是将内容保存到文件的函数。
我的想法是以 server/client 方式使用 goolge 的协议缓冲区:数据使用序列化消息从 Python (R) 传递到 C++,然后在 C++ 中反序列化。计算在 C++ 中是 运行 并且 Python (R) 是 returned 一个 bytes/strings 的列表,每个列表对应于一个序列化的原型对象。
在 Python 中,由于 Pybind11,这就像一个魅力。 但是,在 R 中我得到一个奇怪的错误:
/usr/include/google/protobuf/arena_impl.h:174:60: error: macro "Free" passed 3 arguments, but takes just 1
void (*block_dealloc)(void*, size_t));
我认为这个问题是由于 Rcpp 定义了一个类似于 protobuf 的宏。 以下 MWE 重现了相同的错误。
这是折叠结构
.
├── src
│ ├── rcpp_exports.cpp
├── student.proto
└── test.R
在test.R
Rcpp::sourceCpp(file="src/rcpp_exports.cpp")
在rcpp_exports.cpp
#include <Rcpp.h>
using namespace Rcpp;
#include "student.pb.h"
// [[Rcpp::export]]
std::string foo() {
Student stud;
stud.set_grade(25);
return stud.DebugString();
}
在student.proto
syntax = "proto3";
message Student {
double grade = 1;
bool pass = 2;
}
然后使用
编译protobuf文件> protoc --proto_path=. --cpp_out=./src student.proto
最后我 运行 test.R 文件
> Rscript test.R
获取以下错误日志:
In file included from /usr/include/google/protobuf/arena.h:55:0,
from /home/mario/dev/tesi/test_rproto/src/student.pb.h:24,
from rcpp_exports.cpp:3:
/usr/include/google/protobuf/arena_impl.h:174:60: error: macro "Free" passed 3 arguments, but takes just 1
void (*block_dealloc)(void*, size_t));
^
In file included from /usr/share/R/include/R.h:91:0,
from /home/mario/R/x86_64-pc-linux-gnu-library/3.6/Rcpp/include/Rcpp/r/headers.h:63,
from /home/mario/R/x86_64-pc-linux-gnu-library/3.6/Rcpp/include/RcppCommon.h:29,
from /home/mario/R/x86_64-pc-linux-gnu-library/3.6/Rcpp/include/Rcpp.h:27,
from rcpp_exports.cpp:1:
/usr/share/R/include/R_ext/RS.h:74:37: error: expected identifier before ‘(’ token
#define Free(p) (R_chk_free( (void *)(p) ), (p) = NULL)
^
/usr/share/R/include/R_ext/RS.h:74:47: error: ‘parameter’ declared as function returning a function
#define Free(p) (R_chk_free( (void *)(p) ), (p) = NULL)
^
/usr/share/R/include/R_ext/RS.h:74:50: error: expected ‘)’ before ‘,’ token
#define Free(p) (R_chk_free( (void *)(p) ), (p) = NULL)
^
make: *** [rcpp_exports.o] Error 1
我会推荐一些用于防御性编程的东西:
不要展平命名空间 即 删除
using namespace Rcpp;
并使用前缀显式调用您的函数。通过在包含
Rcpp.h
或其他 R headers.[= 之前定义#define STRICT_R_HEADERS
来要求严格包含(我们不能追溯为默认值) 17=]在没有重新映射的情况下使用 R 函数,即
Rf_error()
通过定义R_NO_REMAP
但 Rcpp 应该为您完成。
通过在包含的内容和方式上稍微自由一些,应该可以避免您在此处发现的冲突。
最后,我们在十多年前写了 RProtoBuf
(它实际上也参与了创建当前的 Rcpp
),但我 从未 收到了您在此处收到的错误消息。所以明明是可以避免的。