Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C中从R包调用C代码_C_R - Fatal编程技术网

在C中从R包调用C代码

在C中从R包调用C代码,c,r,C,R,是否可以在附加的C代码中从现有的R包调用C(或C++)函数 例如,我的包rje中的函数marginTable()使用同名的C函数。我想创建一个包含更多C代码的新包,其中一些代码可以使用C版本的marginTable()。除了将C代码复制到新的文件和包中,我可以从新的C代码中调用该函数吗 还是像这样使用内部代码只是一种不好的做法 [很多人都问过如何从另一个R包调用编译后的代码,但都想在R中调用,而不是用C代码。由@BrodieG提出的R\u registerCallable/R\u GetCCal

是否可以在附加的C代码中从现有的R包调用C(或C++)函数

例如,我的包
rje
中的函数
marginTable()
使用同名的C函数。我想创建一个包含更多C代码的新包,其中一些代码可以使用C版本的
marginTable()
。除了将C代码复制到新的文件和包中,我可以从新的C代码中调用该函数吗

还是像这样使用内部代码只是一种不好的做法


[很多人都问过如何从另一个R包调用编译后的代码,但都想在R中调用,而不是用C代码。

由@BrodieG提出的
R\u registerCallable
/
R\u GetCCallable
解决方案可能比下面的解决方案更好,至少可以在需要注册且调用函数的选择是直接的情况下修改包(下面的示例来自于或多或少复杂的R代码,该代码选择几个函数中的一个传递给C,很像Lappy的有趣参数,其中函数的选择在R中比在C中更容易实现)。当想要公开/访问许多函数时,这也是相关的

一种相关的可能性是在rje包中注册您的C函数,使用类似于在
R\u init\u rje.C

#include <Rinternals.h>
#include <R_ext/Rdynload.h>

SEXP rje(SEXP who) {
    Rprintf("Hello %s\n", CHAR(STRING_ELT(who, 0)));
    return R_NilValue;
}

static const R_CallMethodDef callMethods[] = {
    {".rje", (DL_FUNC) &rje, 1},
    {NULL, NULL, 0}
};

void R_init_rje(DllInfo * info)
{
    R_registerRoutines(info, NULL, callMethods, NULL, NULL);
}
#include <Rinternals.h>
#include <R_ext/Rdynload.h>

/* convenience definition of the function template */
typedef SEXP RJE_C_FUN(SEXP who);

SEXP rje(SEXP who) {
    Rprintf("Hello '%s'\n", CHAR(STRING_ELT(who, 0)));
    return R_NilValue;
}

SEXP use_rje(SEXP rje_c_fun, SEXP who) {
    /* retrieve the function pointer, using an appropriate cast */
    RJE_C_FUN *fun = (RJE_C_FUN *) R_ExternalPtrAddr(rje_c_fun);
    return fun(who);
}

static const R_CallMethodDef callMethods[] = {
    {".rje", (DL_FUNC) &rje, 1},
    {".use_rje", (DL_FUNC) &use_rje, 2},
    {NULL, NULL, 0}
};

void R_init_rje(DllInfo * info)
{
    R_registerRoutines(info, NULL, callMethods, NULL, NULL);
}
C级入口点的地址在R中可用

rje_c = getNativeSymbolInfo(".rje", PACKAGE="rje")
并且可以通过将其用作C函数的参数,在其他程序包中使用,例如

.Call(.use_rje, rje_c$address, "A User")

使用
R CMD SHLIB rje.c
编译,并用作

> dyn.load("rje.so")
> .Call(".use_rje", getNativeSymbolInfo("rje")$address, "A User")
Hello 'A User'
NULL

是的,这是可能的,是的,有一些简单的例子

例如,参见我们的(最近的ish) 包裹 它提供了
serialize()
,供其他CRAN软件包(如我们的 包裹

其他软件包也可以做到这一点:

  • 使用C 代码来自 ;
  • 使用来自的代码 ; 及
  • 这是我用的
在所有示例中,出口商是否声明提供的内容,进口商是否声明已使用

在这种设置中,R可以完成其余的工作,而无需显式链接。

请参阅“编写R扩展”部分;该键似乎使用了对C文件中
R_init_rje
R_registercallable
的调用(@MartinMorgan示例第一块中的最后一个函数)。免责声明:我还没有试过这个。
#include <Rinternals.h>
#include <R_ext/Rdynload.h>

/* convenience definition of the function template */
typedef SEXP RJE_C_FUN(SEXP who);

SEXP rje(SEXP who) {
    Rprintf("Hello '%s'\n", CHAR(STRING_ELT(who, 0)));
    return R_NilValue;
}

SEXP use_rje(SEXP rje_c_fun, SEXP who) {
    /* retrieve the function pointer, using an appropriate cast */
    RJE_C_FUN *fun = (RJE_C_FUN *) R_ExternalPtrAddr(rje_c_fun);
    return fun(who);
}

static const R_CallMethodDef callMethods[] = {
    {".rje", (DL_FUNC) &rje, 1},
    {".use_rje", (DL_FUNC) &use_rje, 2},
    {NULL, NULL, 0}
};

void R_init_rje(DllInfo * info)
{
    R_registerRoutines(info, NULL, callMethods, NULL, NULL);
}
> dyn.load("rje.so")
> .Call(".use_rje", getNativeSymbolInfo("rje")$address, "A User")
Hello 'A User'
NULL