[英]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.