# How can I call String#replace (rb\_str\_replace()) in C API?

**URL:** <https://www.ruby-forum.com/t/how-can-i-call-string-replace-rb-str-replace-in-c-api/188113>\
**Category:** Ruby\
**Created:** [May 6, 2010, 12:35am UTC](https://www.ruby-forum.com/t/how-can-i-call-string-replace-rb-str-replace-in-c-api/188113 "2010-05-06T00:35:33Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![noagenda](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8c91f0/32.png) [@noagenda](https://www.ruby-forum.com/u/noagenda)\
**Post date:** [May 6, 2010, 12:35am UTC](https://www.ruby-forum.com/t/how-can-i-call-string-replace-rb-str-replace-in-c-api/188113/1 "2010-05-06T00:35:33Z")

</div>

Hi all,

I am wrapping a C++ API using SWIG for Ruby and in some cases strings  
need to be allocated and passed to the wrapped function where the  
value of the string itself will need to be modified within the C/C++  
code generated by SWIG. Specifically, I need the String#object\_id to  
stay the same and just have the contents change.

How can I do this with the Ruby C API? I looked at rb\_str\_replace in  
string.c; however, that is not a public function in the C API. After  
searching I found a few postings on this topic, I found that  
rb\_funcall could be initiated but this seems to add some overhead  
which affects performance.

I’m really just looking for a way to take a Ruby string VALUE and  
replace the contents of that object with a C string in the most  
efficient method possible. Can someone help me in doing this or at  
least point me in the right direction?

Thanks,  
-James

---

<div class="post-metadata">

**Author:** ![noagenda](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8c91f0/32.png) [@noagenda](https://www.ruby-forum.com/u/noagenda)\
**Post date:** [May 6, 2010, 3:51am UTC](https://www.ruby-forum.com/t/how-can-i-call-string-replace-rb-str-replace-in-c-api/188113/2 "2010-05-06T03:51:37Z")

</div>

On 5/5/10, James M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> How can I do this with the Ruby C API? I looked at rb\_str\_replace in  
> string.c; however, that is not a public function in the C API. After

Are you using ruby 1.8 or 1.9? 1.9 makes rb\_str\_replace non-static and  
declares it in intern.h. I don’t see it in 1.8’s intern.h, so its very  
likely static there. If you’re on 1.9 I say just go ahead and call it.  
If on 1.8, you’re looking at calling a static function from the  
outside which is difficult and icky at best.

Official policy is that only funcs in ruby.h are considered part of  
the public api, and anything else shouldn’t be used. Actually obeying  
this would mean that such useful and necessary utilities as rb\_str\_new  
and rb\_ary\_new couldn’t be used by extensions, so it has to be taken  
with a gain of salt. I think you should be fairly safe with  
rb\_str\_replace. (Tho ruby maintainers are in effect reserving the  
right to change its calling conventions without warning or regret, it  
is unlikely they will do so.)

> searching I found a few postings on this topic, I found that  
> rb\_funcall could be initiated but this seems to add some overhead  
> which affects performance.

Yeah, that’s slow. And klutsy. Unfortunately, it is what you have to  
do to call a ruby method most of the time :(. If you’re on 1.8, this  
is probably your best option.

> I’m really just looking for a way to take a Ruby string VALUE and  
> replace the contents of that object with a C string in the most  
> efficient method possible. Can someone help me in doing this or at  
> least point me in the right direction?

One other option is to fiddle directly with the fields of struct  
RString, but I don’t recommend that unless you’re really dedicated.

---

<div class="post-metadata">

**Author:** ![noagenda](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8c91f0/32.png) [@noagenda](https://www.ruby-forum.com/u/noagenda)\
**Post date:** [May 6, 2010, 4:20am UTC](https://www.ruby-forum.com/t/how-can-i-call-string-replace-rb-str-replace-in-c-api/188113/3 "2010-05-06T04:20:53Z")

</div>

> > How can I do this with the Ruby C API? I looked at rb\_str\_replace in  
> > string.c; however, that is not a public function in the C API. After
> 
> Are you using ruby 1.8 or 1.9? 1.9 makes rb\_str\_replace non-static and  
> declares it in intern.h. I don’t see it in 1.8’s intern.h, so its very

Unfortunately I am using Ruby 1.8.

> > I’m really just looking for a way to take a Ruby string VALUE and  
> > replace the contents of that object with a C string in the most  
> > efficient method possible. Can someone help me in doing this or at  
> > least point me in the right direction?
> 
> One other option is to fiddle directly with the fields of struct  
> RString, but I don’t recommend that unless you’re really dedicated.

I am thinking about doing this but it would be a pain and probably  
dangerous as you have mentioned. I can probably put something  
together with good performance by tweaking the pointer location and  
string length but I’ll need to get more familiar with the Ruby code  
before I attempt something like this. One good thing is that I am  
creating the Ruby string to be used as the replacement myself in the C+

- code on my own so I shouldn’t need to do type checking. If anyone  
has any pointers on where to find some of the underlying Ruby C data  
structures (e.g. ELTS\_SHARED and STR\_ASSOC flags) then I could use it.

Thanks for your reply… it was helpful to at least confirm the issue  
at hand.

---

<div class="post-metadata">

**Author:** ![noagenda](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8c91f0/32.png) [@noagenda](https://www.ruby-forum.com/u/noagenda)\
**Post date:** [May 6, 2010, 4:45am UTC](https://www.ruby-forum.com/t/how-can-i-call-string-replace-rb-str-replace-in-c-api/188113/4 "2010-05-06T04:45:28Z")

</div>

On 5/5/10, James M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > > efficient method possible. Can someone help me in doing this or at  
> > > creating the Ruby string to be used as the replacement myself in the C+
> 
> - code on my own so I shouldn’t need to do type checking. If anyone  
> has any pointers on where to find some of the underlying Ruby C data  
> structures (e.g. ELTS\_SHARED and STR\_ASSOC flags) then I could use it.

BEWARE: if you go this route, you MUST interface correctly with ruby’s  
garbage collector, or else your program will crash mysteriously in  
unlikely places. Ruby likes to control not only where struct RString  
is allocated, but also the string buffer it points to. The apis for  
using those internal memory management facilities are definitely not  
public, so this gets icky real fast. I’ve never tried to do this and  
can’t offer any advise about how to fool the garbage collector into  
thinking that a string buffer you allocated is actually kosher.

You’re better off trying to call rb\_str\_replace even tho it is static.  
Or maybe porting your app to 1.9. (Which is a nontrivial effort.)

I can’t offer any help with those flags either, other than “Use the  
source, Luke.”. The GC issues are likely to be the biggest challenge.

Good luck!

---

<div class="post-metadata">

**Author:** ![noagenda](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8c91f0/32.png) [@noagenda](https://www.ruby-forum.com/u/noagenda)\
**Post date:** [May 6, 2010, 6:47am UTC](https://www.ruby-forum.com/t/how-can-i-call-string-replace-rb-str-replace-in-c-api/188113/5 "2010-05-06T06:47:12Z")

</div>

> > together with good performance by tweaking the pointer location and  
> > is allocated, but also the string buffer it points to. The apis for  
> > using those internal memory management facilities are definitely not  
> > public, so this gets icky real fast. I’ve never tried to do this and  
> > can’t offer any advise about how to fool the garbage collector into  
> > thinking that a string buffer you allocated is actually kosher.
> 
> You’re better off trying to call rb\_str\_replace even tho it is static.  
> Or maybe porting your app to 1.9. (Which is a nontrivial effort.)
> 
> I can’t offer any help with those flags either, other than “Use the  
> source, Luke.”. The GC issues are likely to be the biggest challenge.

Thanks for the advice :). Yeah, I was actually thinking about  
allocating another Ruby string and doing something similar to what  
rb\_str\_replace does to avoid crashing and GC issues. But it will  
still be tricky. I wish that this was easier…

---

<div class="post-metadata">

**Author:** ![noagenda](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8c91f0/32.png) [@noagenda](https://www.ruby-forum.com/u/noagenda)\
**Post date:** [May 6, 2010, 2:37pm UTC](https://www.ruby-forum.com/t/how-can-i-call-string-replace-rb-str-replace-in-c-api/188113/6 "2010-05-06T14:37:49Z")

</div>

On Thu, May 6, 2010 at 12:45 AM, James M.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Thanks for the advice :). Yeah, I was actually thinking about  
> allocating another Ruby string and doing something similar to what  
> rb\_str\_replace does to avoid crashing and GC issues. But it will  
> still be tricky. I wish that this was easier…

You could use rb\_intern and rb\_funcall\*

VALUE origin\_str;  
VALUE replacement\_str;  
ID replace\_id = rb\_intern(“replace”);

rb\_funcall(orig\_string, replace\_id, 1, replacement\_str);

–  
Rick DeNatale

Blog: [http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)  
Github: [rubyredrick (Rick DeNatale) · GitHub](http://github.com/rubyredrick)  
Twitter: @RickDeNatale  
WWR: [http://www.workingwithrails.com/person/9021-rick-denatale](http://www.workingwithrails.com/person/9021-rick-denatale)  
LinkedIn: [http://www.linkedin.com/in/rickdenatale](http://www.linkedin.com/in/rickdenatale)
