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" "(<type>)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