0

R から使用するために、C から構築された共有オブジェクト ( .so) ファイルを構築しています。オブジェクトをすべてのソース コード、テスト コード、およびヘッダー ファイルとリンク/コンパイルする際に問題があります。

この.soファイルはdyn.load()R で使用してロードされ、対応する関数が呼び出されます。

これはファイルの構造です:

C_header_file1.h // some support functions
C_src_file1.h    // some source code for support functions
C_header_file2.h // some other support functions
C_src_file2.h    // some source code for support functions
C_header_testfunctions.h // testing functions that are called from R for testing
C_src_testfunctions.c  // source code for test functions
C_file_with_main_calling_functions.c // main src file which takes functions from header files (not test header file) to do stuff
C_file_with_main_extern_vars.h // has extern global variables

このファイルには、 (ユーザーが R からメイン関数を呼び出した場合) および(テスト フェーズでユーザーが R からテスト関数を呼び出した場合)C_file_with_main_calling_functions.cによってアクセスできる一連のグローバル変数 (乱数ジェネレーターの仕様) があります。.C_file_with_main_calling_functions.cC_src_testfunctions.c

C_file_with_main_extern_vars.h次のようになります。

// random number generation set up
extern const gsl_rng *gBaseRand;       // global rand number generator
extern unsigned long randSeed;
extern const double lowest_double = -GSL_DBL_MAX;
extern const double highest_double = GSL_DBL_MAX;
extern FILE *fp = NULL;

との両方がC_file_with_main_calling_functions.cありC_src_testfunctions.cます#include "C_file_with_main_extern_vars.h"

共有オブジェクトを作成するにはどうすればよいですか? 次のエラーが表示されます。

R CMD SHLIB C_file_with_main_calling_functions.c ./../test/C_src_testfunctions.c ./../src/src_file1.c ./../src/src_file2.c ./../src/src_file3.c ./../src/src_file6.c ./../src/src_file5.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 C_file_with_main_calling_functions.c -o C_file_with_main_calling_functions.o
In file included from C_file_with_main_calling_functions.c:35:
/mydir/C/include/C_file_with_main_calling_functions.h:15: warning: 'lowest_double' initialized and declared 'extern'
/mydir/C/include/C_file_with_main_calling_functions.h:16: warning: 'highest_double' initialized and declared 'extern'
/mydir/C/include/C_file_with_main_calling_functions.h:17: warning: 'fp' initialized and declared 'extern'
C_file_with_main_calling_functions.c: In function 'func2':
C_file_with_main_calling_functions.c:54: warning: implicit declaration of function 'func1'
C_file_with_main_calling_functions.c: At top level:
C_file_with_main_calling_functions.c:61: warning: conflicting types for 'func1'
C_file_with_main_calling_functions.c:54: warning: previous implicit declaration of 'func1' was here
C_file_with_main_calling_functions.c: In function 'C_file_with_main_calling_functionsC':
C_file_with_main_calling_functions.c:207: warning: passing argument 1 of 'func2' from incompatible pointer type
C_file_with_main_calling_functions.c:271: warning: passing argument 1 of 'gsl_rng_free' discards qualifiers from pointer target type
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 C_file_with_main_calling_functions.so C_file_with_main_calling_functions.o ./../test/C_src_testfunctions.o ./../src/src_file1.o ./../src/src_file2.o ./../src/src_file3.o ./../src/src_file6.o ./../src/src_file5.o -lgsl -lgslcblas -F/usr/local/R.framework/.. -framework R -lintl -Wl,-framework -Wl,CoreFoundation
duplicate symbol _fp in:
    C_file_with_main_calling_functions.o
    ./../test/C_src_testfunctions.o
duplicate symbol _lowest_double in:
    C_file_with_main_calling_functions.o
    ./../test/C_src_testfunctions.o
duplicate symbol _highest_double in:
    C_file_with_main_calling_functions.o
    ./../test/C_src_testfunctions.o
ld: 3 duplicate symbols for architecture x86_64
collect2: ld returned 1 exit status
make: *** [C_file_with_main_calling_functions.so] Error 1

また、2 つの個別の共有オブジェクト (1 つはテスト用、もう 1 つはユーザーが使用するため) も必要ありません (これは私が試して動作します)。

4

1 に答える 1

0

C言語では初期化は定義です。

簡単な例を考えてみましょう:decl.hファイルには単一の宣言が含まれています

#ifdef CORR
extern int i;
#else
extern int i = 5;
#endif

decl.cファイルには定義が含まれています:

#include "decl.h"
int i = 5;
int foo() { return i; }

でコンパイルgcc -DCORR decl.c -cすれば問題ありませんが、extern宣言で初期化してコンパイルしようとすると、多重定義エラーが発生します。

したがって、ヘッダー ファイルには宣言のみを含める必要があり、次のようになります。

extern const gsl_rng *gBaseRand;
extern unsigned long randSeed;
extern const double lowest_double;
extern const double highest_double;
extern FILE *fp;

また、任意の C ファイル (たとえば ) 内に、C_file_with_main_calling_functions.cいくつかの定義を入れることができます。

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;

その後、すべてがエラーなしでコンパイルおよびリンクされます。

于 2013-11-14T12:53:01.897 に答える