我正在构建一个.so
从 C 构建的共享对象 ( ) 文件,以便从 R 中使用。我在将对象与所有源代码、测试代码和头文件链接/编译时遇到问题。
该.so
文件将dyn.load()
在 R 中使用并调用相应的函数来加载。
so
将使用此单个文件
- 通过
testthat
R 中的包来测试功能 - 为包创建一个演示脚本
- 为典型用户公开包中的所有功能
该CMainFile.c
文件有一组全局变量(随机数生成器细节),可以通过CMainFile.c
(当用户从 R 调用主函数时)和testfile.c
(当用户在测试阶段从 R 调用测试函数时)访问.
如何创建允许从 R 调用函数test_get_and_add
(在 testfile 中)和same_as_test_get_and_add
(在 CMainfile 中)的共享对象。
我也不想要两个单独的共享对象(一个用于测试,一个供用户使用)(我已经尝试过并且有效)。
我在这里提供测试文件:
文件1.h
void myaddfunc(double *x, double *y, double *s);
文件2.h
void printadd(double *x, double *y, double *s);
全局变量.h
#include </usr/local/include/gsl/gsl_machine.h>
#include </usr/local/include/gsl/gsl_rng.h>
#include </usr/local/include/gsl/gsl_randist.h>
#include </usr/local/include/gsl/gsl_cdf.h>
extern const gsl_rng *gBaseRand; // global rand number generator
extern unsigned long randSeed;
extern const double lowest_double;
extern const double highest_double;
extern FILE *fp;
CMainFile.h
void set_pseudo_RNG(void);
void get_and_add(double *x, double *s);
文件1.c
#include <stdio.h>
void myaddfunc(double *x, double *y, double *s){
*s = *x + *y;
}
文件2.c
#include <stdio.h>
#include "globalvars.h"
void printadd(double *x, double *y, double *s){
fprintf(fp, "\n Add %f and %f to get: %f. \n", *x, *y, *s);
}
CMainFile.c
#include <stdio.h>
#include <time.h>
#include </usr/local/include/gsl/gsl_machine.h>
#include </usr/local/include/gsl/gsl_rng.h>
#include </usr/local/include/gsl/gsl_randist.h>
#include </usr/local/include/gsl/gsl_cdf.h>
#include "globalvars.h"
#include "file1.h"
#include "file2.h"
// random number generation set up
const gsl_rng *gBaseRand; // global rand number generator
unsigned long randSeed;
const double lowest_double = -GSL_DBL_MAX;
const double highest_double = GSL_DBL_MAX;
FILE *fp = NULL;
// set the global pseudo random number generator
void set_pseudo_RNG(void){
/* specifying to use Mersenne twister as the uniform PRNG */
gBaseRand = gsl_rng_alloc(gsl_rng_mt19937);
srand(time(NULL)); /* initialization for rand() */
randSeed = rand(); /* returns a non-negative integer */
gsl_rng_set(gBaseRand, randSeed); /* seed the PRNG */
}
void same_as_test_get_and_add(double *x, double *s){
set_pseudo_RNG();
get_and_add(x, s);
}
// takes a numeric input x
// generates random y from normal distribution
// calls a function to add x & y. prints sum.
// RNG has to be set up before calling this function
void get_and_add(double *x, double *s){
double *y;
*y = gsl_ran_ugaussian(gBaseRand);
myaddfunc(x, y, s);
printadd(x, y, s);
}
测试文件.c
#include <stdio.h>
#include "globalvars.h"
#include "CMainFile.h"
void test_get_and_add(double *x, double *s){
set_pseudo_RNG();
get_and_add(x, s);
}
这编译:
R CMD SHLIB CMainFile.c testfile.c file1.c file2.c -lgsl -lgslcblas
gcc -std=gnu99 -I/usr/local/R.framework/Resources/include -DNDEBUG -I/sw/include -I/usr/local/include -fPIC -g -O2 -c CMainFile.c -o CMainFile.o
gcc -std=gnu99 -I/usr/local/R.framework/Resources/include -DNDEBUG -I/sw/include -I/usr/local/include -fPIC -g -O2 -c testfile.c -o testfile.o
gcc -std=gnu99 -I/usr/local/R.framework/Resources/include -DNDEBUG -I/sw/include -I/usr/local/include -fPIC -g -O2 -c file1.c -o file1.o
gcc -std=gnu99 -I/usr/local/R.framework/Resources/include -DNDEBUG -I/sw/include -I/usr/local/include -fPIC -g -O2 -c file2.c -o file2.o
gcc -std=gnu99 -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup -single_module -multiply_defined suppress -L/sw/lib -L/usr/local/lib -o CMainFile.so CMainFile.o testfile.o file1.o file2.o -lgsl -lgslcblas -F/usr/local/R.framework/.. -framework R -lintl -Wl,-framework -Wl,CoreFoundation
但不在 R 中运行:
x = vector("numeric", 1)
s = vector("numeric", 1)
dyn.load("CMainFile.so")
.C("test_get_and_add:, as.double(x), as.double(s)
*** caught illegal operation ***
address 0x10484dcd2, cause 'illegal opcode'
Traceback:
1: .C("test_get_and_add", as.double(x), as.double(s))
Possible actions:
1: abort (with core dump, if enabled)
2: normal R exit
3: exit R without saving workspace
4: exit R saving workspace
同样的事情发生在same_as_test_get_and_add
.