Embedding Ruby into a Borland C++ Builder Application

  • Thread starter Mohit Sindhwani
  • Start date
M

Mohit Sindhwani

Hi Everyone

I'm trying to embed Ruby as the scripting engine into a project of
mine. The project is written in Borland C++ Builder (Codergear Turbo
C++ actually). I searched around for clues on embedding Ruby in C++
Builder but the main link I found was frm 2003 and is this one:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/71319

Is there a more recent guide for this?

I've looked at PickAxe 2 and there's a piece of code there that explains
how to embed Ruby (PickAxe 1 has it here)
http://www.rubycentral.com/pickaxe/ext_ruby.html

This includes "ruby.h" which I found in my distribution at:
ruby\src\ruby-1.8.6 and "ruby.h" starts by including "config.h" which it
can't find. I can't find any information on where to provide it from.

I know Windows is less common and Borland C++ Builder even less so, but
a bit of a nudge in the correct direction would help.

Thanks,
Mohit.
 
J

Jari Williamsson

Mohit said:
I'm trying to embed Ruby as the scripting engine into a project of
mine. The project is written in Borland C++ Builder (Codergear Turbo
C++ actually). I searched around for clues on embedding Ruby in C++
Builder but the main link I found was frm 2003 and is this one:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/71319

Is there a more recent guide for this?

I've looked at PickAxe 2 and there's a piece of code there that explains
how to embed Ruby (PickAxe 1 has it here)
http://www.rubycentral.com/pickaxe/ext_ruby.html

This includes "ruby.h" which I found in my distribution at:
ruby\src\ruby-1.8.6 and "ruby.h" starts by including "config.h" which it
can't find. I can't find any information on where to provide it from.

config.h is system-specific and it should build when you call
win32\configure.bat with your environment set up for the C++ Builder
compiler and tools.

To run it with C++ Builder, you need to build from sources to create a
compatible .lib to link with your project. AFAIK, it's basically these
steps for any Windows C++ compiler.

1. Go to a command prompt that has the settings for the compiler and
make tools
2. Create a folder where you want your build and go there
3. Call win32\configure.bat to build config.h and the mak file
4. Run the make tool
5. In your C++ project, link with a lib that was created during the make

In theory, that's what should make it work. Let me know how it works.


Best regards,

Jari Williamsson
 
M

Mohit Sindhwani

Jari said:
Mohit Sindhwani wrote:

config.h is system-specific and it should build when you call
win32\configure.bat with your environment set up for the C++ Builder
compiler and tools.

To run it with C++ Builder, you need to build from sources to create a
compatible .lib to link with your project. AFAIK, it's basically these
steps for any Windows C++ compiler.

1. Go to a command prompt that has the settings for the compiler and
make tools
2. Create a folder where you want your build and go there
3. Call win32\configure.bat to build config.h and the mak file
4. Run the make tool
5. In your C++ project, link with a lib that was created during the make

In theory, that's what should make it work. Let me know how it works.


Best regards,

Jari Williamsson

Thanks Jari - I didn't compile from source. I thought I should have
been able to use a pre-compiled version. So, I was using the version
that came with InstantRails. I'll try out your instructions once I get
back from work today.

Let me also piggy-back new year greetings in this email. Happy new year
everyone!

Cheers,
Mohit.
1/2/2008 | 9:06 AM.
 
M

Mohit Sindhwani

Jari said:
config.h is system-specific and it should build when you call
win32\configure.bat with your environment set up for the C++ Builder
compiler and tools.

To run it with C++ Builder, you need to build from sources to create a
compatible .lib to link with your project. AFAIK, it's basically these
steps for any Windows C++ compiler.

1. Go to a command prompt that has the settings for the compiler and
make tools
2. Create a folder where you want your build and go there
3. Call win32\configure.bat to build config.h and the mak file
4. Run the make tool
5. In your C++ project, link with a lib that was created during the make

In theory, that's what should make it work. Let me know how it works.


Best regards,

Jari Williamsson

HI Jari

Thanks for the advice and pointing me in the correct direction. The
installed version (in InstantRails) did have a folder for bcc32. Here's
what I did, starting from that (mostly following the advice in the
Readme there).

[Getting Ruby built on Borland C++ Builder]
1. From a command window, created a new folder called brb - the
compiler, linker, etc. was in the path (Your step 1)
2. Ran bcc32\configure to create some files (incl config.h)
3. make
4. This died halfway through because it could not find c0x32.obj though
it was in the BDS\4.0\lib directory. To make this work, I went to the
Makefile.sub and updated it to pass the OBJ file path to the ilink32
executable:
LD = ilink32 -q -Gn -j"D:\Program Files\Borland\BDS\4.0\lib\"
5. make (this worked now)
6. make test
7. make DESTDIR="E:\rb_bcc" install

After doing all this, I had the config.h that I needed (in the
ruby\src\ruby-1.8.6\brb directory) and the static libs
(bccwin32-ruby18-static.lib, bccwin32-ruby18.lib) in E:\rb_bcc\lib\ and
the DLL (bccwin32-ruby18.dll) in E:\rb_bcc\bin

No idea yet about the performance of Ruby when compiled with Borland C++.

[Building my application]
For the application, I chose the sample code in 'Programming Ruby' that
shows how to embed Ruby in your application.
1. In Borland C++ Builder, I chose to build a C++ console application.
When I tried to link and build this, it gave me lots of errors about
re-definition (some shown below)
[C++ Error] stdio.h(393): E2167 '_strerror(const char *)' was
previously declared with the language 'C'
[C++ Error] stdio.h(400): E2167 '_wperror(const wchar_t *)' was
previously declared with the language 'C'
[C++ Error] stdio.h(439): E2167 'perror(const char *)' was previously
declared with the language 'C'
2. Then, I created the same thing as a C application and tried to link
it with the static library. Still no go! I got a few errors for
undefined references (below):
[Linker Error] Error: Unresolved external '_errno' referenced from
E:\RB_BCC\LIB\BCCWIN32-RUBY18-STATIC.LIB|file
[Linker Error] Error: Unresolved external '__doserrno' referenced from
E:\RB_BCC\LIB\BCCWIN32-RUBY18-STATIC.LIB|win32
[Linker Error] Error: Unresolved external 'WSAEnumProtocolsA'
referenced from E:\RB_BCC\LIB\BCCWIN32-RUBY18-STATIC.LIB|win32
[Linker Error] Error: Unresolved external 'WSASocketA' referenced from
E:\RB_BCC\LIB\BCCWIN32-RUBY18-STATIC.LIB|win32
3. Not sure what to do with it at this stage. I found a reference that
I had seen earlier
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/73397
and tried to create it as a project to link with the DLL. That worked!!

I can now call a simple Ruby script from my C program. Now, I need to
do 3 more things:
1. Rebuild ruby taking into account some advice about the memory manager.
2. Figure out how to work C++ with Ruby since my current application
uses all the usual pretty things that Builder offers (and needs C++ for
it). This may help a bit: http://metaeditor.sourceforge.net/embed/
3. Figure out how gems work when accessed from embedded Ruby.

I'm sorry that this is a long post but I wanted to jot down all the
stuff I did so that it was available to the next person who may want to
do this. I'm not done yet, but I'd like to put all this down into a
blog post once it all works. But, the above 3 steps stand in the way.

Again, Jari - thanks for getting me started.

Cheers
Mohit.
 
N

Nobuyoshi Nakada

Hi,

At Thu, 3 Jan 2008 00:31:23 +0900,
Mohit Sindhwani wrote in [ruby-talk:285660]:
4. This died halfway through because it could not find c0x32.obj though
it was in the BDS\4.0\lib directory. To make this work, I went to the
Makefile.sub and updated it to pass the OBJ file path to the ilink32
executable:
LD = ilink32 -q -Gn -j"D:\Program Files\Borland\BDS\4.0\lib\"

It is that your setup wasn't enough, as you need the option in
general, so put it in ilink32.cfg file.
[Building my application]
For the application, I chose the sample code in 'Programming Ruby' that
shows how to embed Ruby in your application.
1. In Borland C++ Builder, I chose to build a C++ console application.
When I tried to link and build this, it gave me lots of errors about
re-definition (some shown below)
[C++ Error] stdio.h(393): E2167 '_strerror(const char *)' was
previously declared with the language 'C'

A simple example of declarations with and without extern "C"
doesn't err:

extern "C" void foo(void);
void foo(void);

int main(void)
{
foo();
return 0;
}

I haven't tried to link C++ and am not sure why you failed.
2. Then, I created the same thing as a C application and tried to link
it with the static library. Still no go! I got a few errors for
undefined references (below):
[Linker Error] Error: Unresolved external '_errno' referenced from
E:\RB_BCC\LIB\BCCWIN32-RUBY18-STATIC.LIB|file
[Linker Error] Error: Unresolved external '__doserrno' referenced from
E:\RB_BCC\LIB\BCCWIN32-RUBY18-STATIC.LIB|win32
[Linker Error] Error: Unresolved external 'WSAEnumProtocolsA'
referenced from E:\RB_BCC\LIB\BCCWIN32-RUBY18-STATIC.LIB|win32
[Linker Error] Error: Unresolved external 'WSASocketA' referenced from
E:\RB_BCC\LIB\BCCWIN32-RUBY18-STATIC.LIB|win32

Seems runtime libraries aren't linked.

Anyway, bcc version ruby is almost dead now, and may be
deprecated in the future.
 
M

Mohit Sindhwani

Hi Nakada-san,

Thank you for your replies. My main reason to use BCC is simply because
we're using Codegear's Turbo C++ Professional (Borland C++ Builder) and
would like to embed scripting into our application. I really like
Borland C++ Builder, so I do hope that it doesn't get deprecated :(

My remaining answers are inline.


Nobuyoshi said:
It is that your setup wasn't enough, as you need the option in
general, so put it in ilink32.cfg file.
I think that's correct - I need to update ilink32.cfg to include that.

[Building my application]
For the application, I chose the sample code in 'Programming Ruby' that
shows how to embed Ruby in your application.
1. In Borland C++ Builder, I chose to build a C++ console application.
When I tried to link and build this, it gave me lots of errors about
re-definition (some shown below)
[C++ Error] stdio.h(393): E2167 '_strerror(const char *)' was
previously declared with the language 'C'

A simple example of declarations with and without extern "C"
doesn't err:

extern "C" void foo(void);
void foo(void);

int main(void)
{
foo();
return 0;
}

I haven't tried to link C++ and am not sure why you failed.

Linking in a C program works perfectly fine. The problem that I was
having was in a C++ file. I found some hints from another thread:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/215624

Based on this, I changes win32.h - it originally has a line like:
#if defined(__cplusplus)
extern "C++" {
#endif
((after this, in does #include for stdio.h, stdlib.h, etc.))

I changed the C++ there to "C" and then it works fine. I also had to
remark out one of the lines in missing.h because it seems that one of
the definitions there is now not missing :)

2. Then, I created the same thing as a C application and tried to link
it with the static library. Still no go! I got a few errors for
undefined references (below):
[Linker Error] Error: Unresolved external '_errno' referenced from
E:\RB_BCC\LIB\BCCWIN32-RUBY18-STATIC.LIB|file
[Linker Error] Error: Unresolved external '__doserrno' referenced from
E:\RB_BCC\LIB\BCCWIN32-RUBY18-STATIC.LIB|win32
[Linker Error] Error: Unresolved external 'WSAEnumProtocolsA'
referenced from E:\RB_BCC\LIB\BCCWIN32-RUBY18-STATIC.LIB|win32
[Linker Error] Error: Unresolved external 'WSASocketA' referenced from
E:\RB_BCC\LIB\BCCWIN32-RUBY18-STATIC.LIB|win32

Seems runtime libraries aren't linked.

I think that's the problem. Anyway, right now, the DLL version works
fine. So, I shall investigate this again.
Anyway, bcc version ruby is almost dead now, and may be
deprecated in the future.

I hope not! Again, thanks for the tips!

Best Regards
Mohit.
 
J

Jari Williamsson

Mohit said:
Based on this, I changes win32.h - it originally has a line like:
#if defined(__cplusplus)
extern "C++" {
#endif
((after this, in does #include for stdio.h, stdlib.h, etc.))

I changed the C++ there to "C" and then it works fine. I also had to
remark out one of the lines in missing.h because it seems that one of
the definitions there is now not missing :)

Is there any such thing as extern "C++"? This must be a mistake in the
sources?
I hope not! Again, thanks for the tips!

I also hope not. C++Builder (or as the current name, Developer Studio)
is an excellent RAD tool, and for the occasional apps that needs Ruby
scripting it would be great if everything works. A couple of years ago,
I had to use it Ruby in a C++ Builder project, googled about it and
every discussion thread I searched about it ended in a kind of
"uncertain" state. So I finally ended up building a custom DLL wrapper
to the one-click version of the Ruby DLL library instead. Very
time-consuming, since I had to re-prototype every Ruby C function I needed.


Best regards,

Jari Williamsson
 
M

Mohit Sindhwani

Jari said:
Is there any such thing as extern "C++"? This must be a mistake in the
sources?

I think it's an error - it's in win32.h - I found an earlier link that
had stumbled across this as a problem. But, in that person's case,
changing it back didn't solve the problem. Anyway, it works for me now.
I also hope not. C++Builder (or as the current name, Developer Studio)
is an excellent RAD tool, and for the occasional apps that needs Ruby
scripting it would be great if everything works. A couple of years
ago, I had to use it Ruby in a C++ Builder project, googled about it
and every discussion thread I searched about it ended in a kind of
"uncertain" state. So I finally ended up building a custom DLL wrapper
to the one-click version of the Ruby DLL library instead. Very
time-consuming, since I had to re-prototype every Ruby C function I
needed.


I completely agree that Developer Studio does have a lot of good things and
Best regards,

Jari Williamsson

I've started an article to write about the process of embedding Ruby
into Borland C++ Builder which I shall put on my blog at:
http://notepad.onghu.com/2008/1/2/codegear-turbo-c-and-ruby - and will
jot down the notes as I go through the process. I think I'm keen to see
C++ Builder survive and I love Ruby - together, they can do some
fantastic things (rapid development, rapid development!)

Cheers
Mohit.
 
N

Nobuyoshi Nakada

Hi,

At Thu, 3 Jan 2008 13:49:33 +0900,
Mohit Sindhwani wrote in [ruby-talk:285753]:
Linking in a C program works perfectly fine. The problem that I was
having was in a C++ file. I found some hints from another thread:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/215624

Based on this, I changes win32.h - it originally has a line like:
#if defined(__cplusplus)
extern "C++" {
#endif
((after this, in does #include for stdio.h, stdlib.h, etc.))

I changed the C++ there to "C" and then it works fine. I also had to
remark out one of the lines in missing.h because it seems that one of
the definitions there is now not missing :)

It must be C++ due to a template without extern "C++", in
math.h of MSVC6. Microsoft also seems to have considered this
is a problem and fixed it in VC8.

The re-definitions in BCC are caused by C linkage and using std
namespace. Although it also seems quite curious, it should be
fixed as a workaround for VC6.
 
N

Nobuyoshi Nakada

Hi,

At Fri, 4 Jan 2008 01:06:37 +0900,
Mohit Sindhwani wrote in [ruby-talk:285846]:
I think it's an error - it's in win32.h - I found an earlier link that
had stumbled across this as a problem. But, in that person's case,
changing it back didn't solve the problem. Anyway, it works for me now.

It's valid. The C++ spec requires extern "C" and "C++" at
least. Other linkages e.g., "pascal", "fortran", "ada", etc,
can be implementation defined.
I completely agree that Developer Studio does have a lot of good things and

Maybe, but Borland make is too silly, it should not be named as
`make'.
 
M

Mohit Sindhwani

Nobuyoshi said:
Hi,

At Fri, 4 Jan 2008 01:06:37 +0900,
Mohit Sindhwani wrote in [ruby-talk:285846]:
I think it's an error - it's in win32.h - I found an earlier link that
had stumbled across this as a problem. But, in that person's case,
changing it back didn't solve the problem. Anyway, it works for me now.

It's valid. The C++ spec requires extern "C" and "C++" at
least. Other linkages e.g., "pascal", "fortran", "ada", etc,
can be implementation defined.

I completely agree that Developer Studio does have a lot of good things and

Maybe, but Borland make is too silly, it should not be named as
`make'.

Haha.. I see the point you 'make'! But, thanks both of you for your
help. I shall put up the instructions for making Ruby 1.8.6 work from
within a C++ Builder application soon. Then, I shall look for the other
items I had on my list (performance and memory management).

Cheers,
Mohit.
1/4/2008 | 12:38 AM.
 

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,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top