Extending ruby with crypto++

D

Dominik Werder

Hello everybody,

I'd like to use some encryption functions from the crypto++ library
from within ruby.
To achieve this, I tried to make C-Wrapper functions around the C++
library archive.
But to link it against the C++ Archive, I have to use the g++
compiler, otherwise the linker doesn't find symbols (any workaround
for this?!?)
The bad thing is that g++ doesn't compile the ruby extension properly.
I'm very new to C++, so I've no idea how to solve this.
Does anybody know of a ruby extension that wraps C++ libs where I can
spoof a little bit?

bye!
Dominik
 
N

nobu.nokada

Hi,

At Wed, 8 Sep 2004 08:30:08 +0900,
Dominik Werder wrote in [ruby-talk:111808]:
But to link it against the C++ Archive, I have to use the g++
compiler, otherwise the linker doesn't find symbols (any workaround
for this?!?)

Add have_library("stdc++") to extconf.rb.
The bad thing is that g++ doesn't compile the ruby extension properly.
I'm very new to C++, so I've no idea how to solve this.
Does anybody know of a ruby extension that wraps C++ libs where I can
spoof a little bit?

How doesn't it work properly?
 
D

Dominik Werder

Add have_library("stdc++") to extconf.rb.
I don't use any build system for this little wrapper, or do you mean I
should add this to the ruby source and recompile ruby? I guess no :)

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 (*)(...)'

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.

- 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.....

I tried also linking with g++ cruse.o cr.o -lcryptopp -lstdc++ because
you said I should include the libstdc++

I'm stuck.


If I strip away anything from cRubyTest.c that has to do with ruby, it
compiles with g++ and links properly, but doesn't do anything useful
of course :((


It should be possible to take a object made with gcc and one made with
g++ and link them together properly, shouldn't it?


Please help me!
Dominik
 
T

ts

D> bash-2.05b$ g++ -c cRubyTest.c
D> cRubyTest.c: In function `void Init_cRubyTest()':
D> cRubyTest.c:56: error: invalid conversion from `VALUE (*)(long
D> unsigned int)'
D> to `VALUE (*)(...)'

It's best if you give the complete example, but try it with
RUBY_METHOD_FUNC()


Guy Decoux
 
T

ts

D> which contains two really small files (3 lines) and a README with a
D> detailed description of the problem. You can try it on every gcc/g++,
D> it depends on nothing, just demonstrates the problem.

It's called "name mangling". You must compile a.c with g++

Look at bdb-0.5.1, you have an example with bdbxml.cc where Init_bdbxml()
is defined inside a

extern "C" {

}


Guy Decoux
 
G

gabriele renzi

Dominik Werder ha scritto:
Hello everybody,

I'd like to use some encryption functions from the crypto++ library
from within ruby.

I won't help you, but are you sure you could'nt mock up something with
the openssl binding? It could svae you lot of work..
 
N

nobu.nokada

Hi,

At Wed, 8 Sep 2004 17:25:07 +0900,
Dominik Werder wrote in [ruby-talk:111830]:
I don't use any build system for this little wrapper, or do you mean I
should add this to the ruby source and recompile ruby? I guess no :)

Then how do you compile it?

I mean you have to create extconf.rb:

have_library("stdc++")
create_makefile("your_libname")
 
F

Florian Pflug

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
 
D

Dominik Werder

Hi,

At Wed, 8 Sep 2004 17:25:07 +0900,
Dominik Werder wrote in [ruby-talk:111830]:
I don't use any build system for this little wrapper, or do you mean I
should add this to the ruby source and recompile ruby? I guess no :)

Then how do you compile it?

I mean you have to create extconf.rb:

have_library("stdc++")
create_makefile("your_libname")

When it was plain C without the C++ stuff I just used gcc from
commandline to make a shared object..
 
D

Dominik Werder

Found it, the keyword is extern instead of export, but I solved it as
you said:

just said
extern "C" int myfunc() { .. }

If I put the extern statement into the header file, the gcc complains.
So I removed it from the header file and also had to remove the
#incude from the cpp file, because the declarations are not the same,
obviously, but it works!

bye!
Dominik
 
E

Elias Athanasopoulos

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 (*)(...)'

This macro is taken from SWIG:

#ifdef __cplusplus
# ifndef RUBY_METHOD_FUNC /* These definitions should work for Ruby 1.4.6
*/
# define VALUEFUNC(f) ((VALUE (*)()) f)
# define VOIDFUNC(f) ((void (*)()) f)
# else
# ifndef ANYARGS /* These definitions should work for Ruby 1.6 */
# define VALUEFUNC(f) ((VALUE (*)()) f)
# define VOIDFUNC(f) ((RUBY_DATA_FUNC) f)
# else /* These definitions should work for Ruby 1.7 */
# define VALUEFUNC(f) ((VALUE (*)(ANYARGS)) f)
# define VOIDFUNC(f) ((RUBY_DATA_FUNC) f)
# endif
# endif
#else
# define VALUEFUNC(f) (f)
# define VOIDFUNC(f) (f)
#endif

It's pretty safe to use it in your extension. You should
use this macro in rb_define_method() and similar functions:

/* Define method. */
rb_define_method(klass, name, VALUEFUNC(f), -1);

Regards,
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top