From: Florian Pflug Date: 2004-09-08T20:27:05+09:00 Subject: Re: Extending ruby with crypto++ On Wed, September 8, 2004 10:25, Dominik Werder said: >> How doesn't it work properly? > I'll try to explain: > I have two Files: > > - The first one is a cpp file that wraps the functionality I want into > a function. I compile this one with g++ to an object file > > - The second file is a .c file (my ruby extension). I compile this > with gcc because g++ gives errors like: > > bash-2.05b$ g++ -c cRubyTest.c > cRubyTest.c: In function `void Init_cRubyTest()': > cRubyTest.c:56: error: invalid conversion from `VALUE (*)(long > unsigned int)' > to `VALUE (*)(...)' C++ is much stricter when it comes to what kindes of type-casts are allowed - especially when you use the "old-style" "()value" casts (e.g "(char*)void_ptr"). You might have to use new-style C++-only casting using static_cast, reinterpret_cast,... > I got the code from the pickaxe book and don't know with this doesn't > work with g++. gcc compiles correctly to an object file. See above. > - But if I try to link (with g++ cRubyTest.o cr.o -lcryptopp) ld sais: > cRubyTest.o(.text+0x1b): In function `cfunc': > : undefined reference to `GenerateRSAKey' > collect2: ld returned 1 exit status > > where GenerateRSAKey is the wrapper function from the cpp file..... When compiling plain C code, the symbols in the generated .o file are named like the function they are describing. With C++, however, it works differently, because you can have more than one function with the same name (but different count or types or arguments) in C++. The compiler therefore encodes the signature (the order, count, and type of the arguments) of a function into its name - e.g. the symbol for "int my_func(char*, int)" might be "int__my_func__char_star__int" (the actual name-mangling the gcc uses is different, and less human-readable, but you get the idea). Since you compiled one file with gcc, and the other with g++, the same function "GenerateRSAKey" is mapped to different symbol names - which of course makes the linker complain that it can't find the referenced symbols. I believe you have to wrap the function-declaration of GenerateRSAKey" (inside your cpp-source) in an 'export "C"' clause. This tells the compiler that it should generate symbols compatible with C, algtough the file contains C++ code. So, instead of declaring GenerateRSAKey with return_type GenerateRSAKey(type_1 arg1, type_2 arg2, ...) ; you declare it writing export "C" { return_type GenerateRSAKey(type_1 arg1, type_2 arg2, ...) ; } I hope I got the syntax of the "export" clause right - I haven't activly programmed C++ for a few years, and I'm too lazy to look it up right now ;-)) greetings, Florian Pflug