Embedding Ruby into a Borland C++ Builder Application

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.

Mohit Sindhwani wrote:

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

Jari Williamsson wrote:

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.

Jari Williamsson 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

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: ruby embedded into c++
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.

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.

···

--
Nobu Nakada

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 :frowning:

My remaining answers are inline.

Nobuyoshi Nakada wrote:

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.
  

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 :slight_smile:

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.

Mohit Sindhwani wrote:

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 :slight_smile:

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

Anyway, bcc version ruby is almost dead now, and may be
deprecated in the future.
  
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

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 :slight_smile:

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.

···

--
Nobu Nakada

Jari Williamsson wrote:

Mohit Sindhwani wrote:

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 :slight_smile:

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.

Anyway, bcc version ruby is almost dead now, and may be
deprecated in the future.
  
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.

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.

Hi,

At Fri, 4 Jan 2008 01:06:37 +0900,
Mohit Sindhwani wrote in [ruby-talk:285846]:

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

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

···

--
Nobu Nakada

Nobuyoshi Nakada wrote:

Hi,

At Fri, 4 Jan 2008 01:06:37 +0900,
Mohit Sindhwani wrote in [ruby-talk:285846]:
  

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