Как обернуть стороннюю DLL для использования в R? - PullRequest
0 голосов
/ 30 октября 2018

Мне нужно использовать существующий сторонний API, который поставляется с файлами * .h и * .dll для загрузки данных в R. Функции, предоставляемые dll, не могут вызываться напрямую, поэтому мне нужно обернуть их для вызова их из R. Для того, чтобы ознакомиться с этим, я сделал небольшой пример DLL (на основе HOWTO со страницы MINGW здесь , я поместил исходный код файлов в конце поста) , В нем есть только одна функция, которая удваивает целочисленный ввод. Я могу прекрасно скомпилировать dll, а также использовать его в exe-файле, чтобы он работал. Это на Windows 10.

Я не уверен, как правильно использовать это в R. Я создал пакет (с именем testwithdll2), поместил файл заголовка и DLL в «src» вместе с функцией оболочки. Когда я пытаюсь скомпилировать пакет, я получаю следующие сообщения об ошибках с неопределенной ссылкой:

C:/Rtools/mingw_64/bin/gcc  -I"C:/PROGRA~1/R/R-35~1.1/include" -DNDEBUG
-O2 -Wall  -std=gnu99 -mtune=generic -c mydouble_c.c -o mydouble_c.o
C:/Rtools/mingw_64/bin/gcc -shared -s -static-libgcc -o testwithdll2.dll
tmp.def mydouble_c.o -LC:/PROGRA~1/R/R-35~1.1/bin/x64 -lR
mydouble_c.o:mydouble_c.c:(.text+0xc): undefined reference to `__imp_timestwo'
collect2.exe: error: ld returned 1 exit status

Любые указатели на то, что могло пойти не так, с благодарностью.

example_dll.h:

#ifndef EXAMPLE_DLL_H
#define EXAMPLE_DLL_H

#ifdef __cplusplus
extern "C" {
#endif

#ifdef BUILDING_EXAMPLE_DLL
#define EXAMPLE_DLL __declspec(dllexport)
#else
#define EXAMPLE_DLL __declspec(dllimport)
#endif

int EXAMPLE_DLL timestwo(int x);

#ifdef __cplusplus
}
#endif


#endif  // EXAMPLE_DLL_H

example_dll.cpp:

#include <stdio.h>
#include "example_dll.h"

int timestwo(int x)
{
        return 2 * x;
}

mydouble.c (в папке src пакета r):

#include "example_dll.h"
void mydouble(int* a){
  *a = timestwo(*a);
}

timestwo.R (функция оболочки, в папке R):

#' @useDynLib testwithdll2 mydouble
#' @export
timestwo <- function(n){
  .C("mydouble",n )
  n
}

1 Ответ

0 голосов
/ 01 ноября 2018

Я понял, что делать. Нужно было использовать файл makevars со следующими строками:

MAKEVARS:

PKG_CPPFLAGS= -I.
PKG_LIBS= -L. -lexample_dll

Также было необходимо добавить вызов useDynlib к example_dll.dll в пространстве имен перед вызовом testwithdll2.dll. Это также означало, что для вызова .C требовалось указать параметр PACKAGE, поэтому мне пришлось изменить оболочку r на:

timestwo.R

#' @useDynLib example_dll
#' @useDynLib testwithdll2
#' @export
timestwo <- function(n){
  .C("mydouble",n, PACKAGE = "testwithdll2")[[1]]
}

Теперь все работает как положено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...