R: указатель на функцию c

Как передать указатель на функцию из кода C в R (используя External R) и после вызова этой функции из R ??

Что-то вроде:

C:

typedef void (* FunctionPtr)();
SEXP ans;
PROTECT(ans = /* ?some code? */);
R_tryEval(ans, R_GlobalEnv, NULL);
UNPROTECT(1);

Р:

callback_function()

РЕДАКТИРОВАТЬ:
Сообщение @Romain Francois было очень полезным.
Myapp код:

namespace
{
void callback()
{
std::cout << "callback\n" << std::flush;
}
}
class Worker
{
public:
/*...*/
void initialize(argc, argv)
{
Rf_initEmbeddedR(argc, argv);

SEXP ans, val;
typedef void (* FunctionPtr)();

PROTECT(ans = Rf_lang2(Rf_install("source"), Rf_mkString("script.R")));
R_tryEval(ans, R_GlobalEnv, NULL);
UNPROTECT(1);

PROTECT(val = Rf_ScalarInteger((int)(&callback)));
/* pass the address of the pointer to a function */
PROTECT(ans = Rf_lang2(Rf_install("setCallback"), val));
R_tryEval(ans, R_GlobalEnv, NULL);
UNPROTECT(2);
}
void uninitialize()
{
Rf_endEmbeddedR(0);
}
};

R и Rcpp
script.R

###################
sourceCpp("utils.cpp")
###################
callback <- function()
{
callCallback()
}

utils.cpp

#include <Rcpp.h>

using namespace Rcpp;

typedef void (* Callback)();
static Callback spCallback = 0;

// [[Rcpp::export]]
void callCallback()
{
if (spCallback) {
spCallback();
} else {
Rprintf("ERROR: callback is not set");
}
}
// [[Rcpp::export]]
void setCallback(const int address)
{
spPlaceOrder = (Callback)address;
}

4

Решение

Внешние указатели — это то, что вы ищете. Они требуют, чтобы вы инкапсулировали указатели на произвольные структуры данных. Слово данные Здесь важно, и указатели на функции — это другое животное. Если вы хотите использовать C++ а также RcppЯ хотел бы создать небольшой класс, который инкапсулирует указатель на функцию:

typedef void (* FunctionPtr)();
class FunctionPointer {
FunctionPtr ptr;
public:
FunctionPointer( FunctionPtr ptr_) : ptr(ptr_){}
} ;

а затем создать XPtr<FunctionPointer>:

#include <Rcpp.h>
using namespace Rcpp ;

// your callback function
void callback(){
Rprintf( "hello from callback\n" ) ;
}

// The function that creates an external pointer to your
// callback
// [[Rcpp::export]]
XPtr<FunctionPointer> create_ptr(){
return XPtr<FunctionPointer>( new FunctionPointer(callback) );
}

// The function that invokes the callback
// [[Rcpp::export]]
void invokeCallback( XPtr<FunctionPointer> callback){
callback->ptr() ;
}

На стороне R вы можете использовать лексическую область видимости, например, чтобы обернуть внешний указатель в функцию R:

callback <- local( {
ptr <- create_ptr()
function(){
invokeCallback( ptr )
invisible(NULL)
}
} )
callback()
6

Другие решения

Другой способ заключается в использовании InternalFunction класс в Rcpp:

#include <Rcpp.h>
using namespace Rcpp ;

void callback(){
Rprintf( "hello from calback\n" ) ;
}

// [[Rcpp::export]]
InternalFunction get_callback(){
return InternalFunction(callback) ;
}

Реализация похожа на то, что я описал в другом ответе. Вещи на стороне R заботятся Rcpp:

callback <- get_callback()
callback()
4

Сначала загрузите библиотеку:

dyn.load("yourDLL.dll")

Тогда используйте:

Функции для выполнения вызовов к скомпилированному коду, который был загружен в R.

Увидеть Р ФФИ

РЕДАКТИРОВАТЬ:

Сначала скомпилируйте ваш C-код. На Windows это следующее, но на других аналогичных ОС:

gcc mylib.c -shared -o mylib.dll

а затем в R:

dyn.load("mylib.dll")
tmp1  <- as.raw(rep(0,4))   # 4 bytes to be sent to the function's argument
tmp2<-.C("yourFunctionName", tmp1)   # tmp2 now has the data returned by the func

Обратите внимание, что в c ++ (не c) имя функции должно быть искаженное имя

0
По вопросам рекламы [email protected]