![](/img/trans.png)
[英]Why is fetestexcept in C++ compiled to a function call rather than inlined
[英]Why do I get a segfault when calling my C++ function with .Call rather than .C?
我的最终目标是从 R 中调用一些 C++ 函数,这是我遇到障碍的 MNWE。 如果我正确读取房间,当我用.Call
调用我的 function 但当我用.C
调用它时,我似乎遇到了段错误。
这是我的短 C++ function
// test.cpp
#include <iostream>
extern "C" void fnTest() {
std::cout << "Hello" << std::endl;
}
然后我用它编译
R CMD SHLIB -o test.so test.cpp
其中给出了以下 output:
g++ -std=gnu++11 -shared -L/usr/lib64/R/lib -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -o te
st.so test.o -L/usr/lib64/R/lib -lR
现在在 R 我做了
> dyn.load("test.so")
> .C("fnTest")
Hello
list()
> .Call("fnTest")
Hello
*** caught segfault ***
address 0x30, cause 'memory not mapped'
Possible actions:
1: abort (with core dump, if enabled)
2: normal R exit
3: exit R without saving workspace
4: exit R saving workspace
Selection:
我为这两个函数阅读的文档在这里,似乎并没有表明这两个函数的调用格式有很大差异。 我尝试了其他几种变体(例如,我能够成功地将 arguments 传递给.C
但不是.Call
)并且没有任何成功。
从 R 中调用.Call
function 的正确方法是什么?
除了这个最小的例子之外,关于我的最终用例的一些注释,希望这不是一个XY 问题:我有一个具有许多复杂依赖项的项目,我知道如何使用 CMake 但不是直接从 g++ 构建。 我能够从这个项目构建一个共享库,然后我可以链接到一个“R 兼容”共享库( R CMD SHLIB -o test.so test.cpp -L/path/to/my/lib/ -l my_lib_name
) 我能够将dyn.load()
到我的 R 环境中。 那时我遇到了上述.C
与.Call
问题。
通过阅读一些额外的文档(我应该在第一遍中找到),我相信你不能。调用返回类型为void
的.Call
。 我找不到明确提及这一点,但文档中没有示例(例如this section )列出了SEXP
以外的返回类型,并且文档中有一次声明:
您将处理的所有 R 对象都将使用 SEXP 类型处理
On the other hand, as documented in the Interface functions.C and.Fortran section , any function that you .C
must have a return type of void:
请注意,编译后的代码不应返回任何内容,除非通过其 arguments:C 函数应为 void 类型,Fortran 子程序应为子例程。
以下是一些可以在 OP 中编译的示例。 .Call
函数似乎没有默认的“null”返回类型,但allocVector(REALSXP, 0)
R_NilValue
似乎运行良好。
// test.cpp
#include <R.h>
#include <Rinternals.h>
extern "C" void fnPrintC() {
Rprintf("Hello world!\n");
}
extern "C" SEXP fnPrintCall() {
Rprintf("Hello world!\n");
// return allocVector(REALSXP, 0);
return R_NilValue;
}
extern "C" SEXP fnAddCall(SEXP a, SEXP b) {
double* xa = REAL(a);
double* xb = REAL(b);
SEXP ans = allocVector(REALSXP, 2);
REAL(ans)[0] = *xa + *xb;
REAL(ans)[1] = *xa - *xb;
return ans;
}
在这里,它们被称为 R。 请注意,如果我们不想看到它,我们可以将 ( void
) output 发送到虚拟变量x
。
> dyn.load("test.so")
> x <- .C("fnPrintC")
> Hello world!
> x <- .Call("fnPrintCall")
> Hello world!
> .Call("fnAddCall", 4, 3)
> [1] 7 1
一般来说,上面链接的文档很有帮助,我建议任何有类似问题的人从那里开始,我当然希望我能早点更彻底地阅读它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.