# Converting array of Strings to C array of strings

**URL:** <https://www.ruby-forum.com/t/converting-array-of-strings-to-c-array-of-strings/211637>\
**Category:** Ruby-Gnome 2\
**Created:** [September 9, 2011, 2:28pm UTC](https://www.ruby-forum.com/t/converting-array-of-strings-to-c-array-of-strings/211637 "2011-09-09T14:28:53Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![dubstep](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/cdc98d/32.png) [@dubstep](https://www.ruby-forum.com/u/dubstep)\
**Post date:** [September 9, 2011, 2:28pm UTC](https://www.ruby-forum.com/t/converting-array-of-strings-to-c-array-of-strings/211637/1 "2011-09-09T14:28:53Z")

</div>

This pattern is repeated a couple of times in glib2 and gtk2:

```
for (i = 0; i < gargc; i++) {
    if (TYPE(RARRAY_PTR(argary)[i]) == T_STRING) {
        gargv[i+1] = RVAL2CSTR(RARRAY_PTR(argary)[i]);
    }
    else {
        gargv[i+1] = g_strdup("");
    }
}

```

The TYPE() == T\_STRING test seems like a poor choice. Shouldn’t we at  
least try using #to\_str?

Also, as this pattern is repeated I really think that we should have a  
utility function for it. I’ll write it, but I need input on the  
TYPE() comparison above.

---

<div class="post-metadata">

**Author:** ![Nikolai\_W](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/df705f/32.png) [@Nikolai\_W](https://www.ruby-forum.com/u/Nikolai_W)\
**Post date:** [September 10, 2011, 5:33am UTC](https://www.ruby-forum.com/t/converting-array-of-strings-to-c-array-of-strings/211637/2 "2011-09-10T05:33:33Z")

</div>

Hi,

In [CADdV=removed\_email\_address@domain.invalid](mailto:CADdV=removed_email_address@domain.invalid)  
“[ruby-gnome2-devel-en] Converting array of Strings to C array of  
strings” on Fri, 9 Sep 2011 14:28:05 +0200,  
Nikolai W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> The TYPE() == T\_STRING test seems like a poor choice. Shouldnt we at  
> least try using #to\_str?
> 
> Also, as this pattern is repeated I really think that we should have a  
> utility function for it. Ill write it, but I need input on the  
> TYPE() comparison above.

Use the following code that uses #to\_str:

for (i = 0; i \< gargc; i++) {  
gargv[i+1] = RVAL2CSTR(RARRAY\_PTR(argary)[i]);  
}

## Thanks,

kou

---

<div class="post-metadata">

**Author:** ![Nikolai\_W](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/df705f/32.png) [@Nikolai\_W](https://www.ruby-forum.com/u/Nikolai_W)\
**Post date:** [September 10, 2011, 12:33pm UTC](https://www.ruby-forum.com/t/converting-array-of-strings-to-c-array-of-strings/211637/3 "2011-09-10T12:33:37Z")

</div>

2011/9/10 Kouhei S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> Nikolai W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > The TYPE() == T\_STRING test seems like a poor choice. Shouldn’t we at  
> > least try using #to\_str?

> Use the following code that uses #to\_str:
> 
> for (i = 0; i \< gargc; i++) {  
> gargv[i+1] = RVAL2CSTR(RARRAY\_PTR(argary)[i]);  
> }

Good. I will update rbg\_rval2argv (well, remove it, I suppose).

---

<div class="post-metadata">

**Author:** ![Nikolai\_W](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/df705f/32.png) [@Nikolai\_W](https://www.ruby-forum.com/u/Nikolai_W)\
**Post date:** [October 2, 2011, 10:25am UTC](https://www.ruby-forum.com/t/converting-array-of-strings-to-c-array-of-strings/211637/4 "2011-10-02T10:25:27Z")

</div>

Hi,

2011/9/10 Kouhei S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> > ```
> > gargv[i+1] = RVAL2CSTR(RARRAY_PTR(argary)[i]);
> > 
> > ```
> > 
> > utility function for it. Ill write it, but I need input on the  
> > TYPE() comparison above.
> 
> Use the following code that uses #to\_str:
> 
> for (i = 0; i \< gargc; i++) {  
> gargv[i+1] = RVAL2CSTR(RARRAY\_PTR(argary)[i]);  
> }

BTW. The code is not GC-safe.  
Suppose argary[0].to\_str returns a newly allocated string object S and  
garbage collection happens during execution of argary[1].to\_str.  
In this case, it is possible that S is reclaimed by GC and gargv[0]  
becomes dangling pointer.

– Masahiro

---

<div class="post-metadata">

**Author:** ![Nikolai\_W](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/df705f/32.png) [@Nikolai\_W](https://www.ruby-forum.com/u/Nikolai_W)\
**Post date:** [October 2, 2011, 11:43am UTC](https://www.ruby-forum.com/t/converting-array-of-strings-to-c-array-of-strings/211637/5 "2011-10-02T11:43:48Z")

</div>

On Sun, Oct 2, 2011 at 10:24, Masahiro S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> > for (i = 0; i \< gargc; i++) {  
> > gargv[i+1] = RVAL2CSTR(RARRAY\_PTR(argary)[i]);  
> > }
> 
> BTW. The code is not GC-safe.  
> Suppose argary[0].to\_str returns a newly allocated string object S and  
> garbage collection happens during execution of argary[1].to\_str.  
> In this case, it is possible that S is reclaimed by GC and gargv[0]  
> becomes dangling pointer.

How do we solve this? This problem probably appears in a lot of places.

---

<div class="post-metadata">

**Author:** ![Nikolai\_W](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/df705f/32.png) [@Nikolai\_W](https://www.ruby-forum.com/u/Nikolai_W)\
**Post date:** [October 2, 2011, 2:41pm UTC](https://www.ruby-forum.com/t/converting-array-of-strings-to-c-array-of-strings/211637/6 "2011-10-02T14:41:26Z")

</div>

I’m sorry but I misunderstood.  
RVAL2CSTR stores results of #to\_str into RARRAY\_PTR(argary)[i],  
so that newly allocated objects are reachable and will not be GC’ed.

(But, of course, modifying RARRAY\_PTR(argary)[i] directly is not a  
good idea and causes problems in some cases. For example it modify  
the array even if the array is frozen. Also it might affect other arrays  
if contents of the array are shared with other arrays.)

Regards,

– Masahiro

2011/10/2 Nikolai W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

---

<div class="post-metadata">

**Author:** ![Nikolai\_W](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/df705f/32.png) [@Nikolai\_W](https://www.ruby-forum.com/u/Nikolai_W)\
**Post date:** [October 2, 2011, 6:49pm UTC](https://www.ruby-forum.com/t/converting-array-of-strings-to-c-array-of-strings/211637/7 "2011-10-02T18:49:09Z")

</div>

On Sun, Oct 2, 2011 at 14:40, Masahiro S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> I’m sorry but I misunderstood.  
> RVAL2CSTR stores results of #to\_str into RARRAY\_PTR(argary)[i],  
> so that newly allocated objects are reachable and will not be GC’ed.

Oh, yes, that’s true, even for arrays.

> (But, of course, modifying RARRAY\_PTR(argary)[i] directly is not a  
> good idea and causes problems in some cases. For example it modify  
> the array even if the array is frozen. Also it might affect other arrays  
> if contents of the array are shared with other arrays.)

Yes, this is probably even worse. Hm, I guess copying the Ruby array  
and then using RVAL2CSTR on the copy is the best thing to do. I’ll  
look into creating a patch. (I have some other things queued up  
affecting this code anyway.)

---

<div class="post-metadata">

**Author:** ![Nikolai\_W](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/df705f/32.png) [@Nikolai\_W](https://www.ruby-forum.com/u/Nikolai_W)\
**Post date:** [October 2, 2011, 1:15pm UTC](https://www.ruby-forum.com/t/converting-array-of-strings-to-c-array-of-strings/211637/8 "2011-10-02T13:15:05Z")

</div>

On Sun, Oct 2, 2011 at 11:42, Nikolai W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > becomes dangling pointer.
> 
> How do we solve this? This problem probably appears in a lot of places.

I can only think of having two arrays, one for VALUEs and one for C  
pointers. Does that work? And, is there an easier way of doing it?

---

<div class="post-metadata">

**Author:** ![Nikolai\_W](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/df705f/32.png) [@Nikolai\_W](https://www.ruby-forum.com/u/Nikolai_W)\
**Post date:** [October 8, 2011, 4:20pm UTC](https://www.ruby-forum.com/t/converting-array-of-strings-to-c-array-of-strings/211637/9 "2011-10-08T16:20:55Z")

</div>

On Sun, Oct 2, 2011 at 18:48, Nikolai W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > if contents of the array are shared with other arrays.)
> 
> Yes, this is probably even worse. Hm, I guess copying the Ruby array  
> and then using RVAL2CSTR on the copy is the best thing to do. I’ll  
> look into creating a patch. (I have some other things queued up  
> affecting this code anyway.)

OK, so the new interface will be

const gchar \*\*rbg\_rval2strv(volatile VALUE \*ary, long \*n);  
#define RVAL2STRS(ary, n) rbg\_rval2strv(&(ary), &(n))

Is that fine with everyone? I would have prefered

#define RVAL2STRS(ary, n) rbg\_rval2strv(ary, n)

simply because it’s more explicit, but just passing in the variable  
meshes with RVAL2STR/StringValue/StringValuePtr.

What do you think?

Once we agree on an interface I will apply all the necessary changes.

(The same interface will then apply to all RVAL2\*(ary, n)  
macros/functions.)

Note that the functionality will change so that

\*ary = rb\_ary\_dup(rb\_ary\_to\_ary(\*ary));

will be performed before modifying the values or ary, thus making sure  
that we don’t change either ary or the result of #to\_ary.

---

<div class="post-metadata">

**Author:** ![Nikolai\_W](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/df705f/32.png) [@Nikolai\_W](https://www.ruby-forum.com/u/Nikolai_W)\
**Post date:** [October 10, 2011, 2:18pm UTC](https://www.ruby-forum.com/t/converting-array-of-strings-to-c-array-of-strings/211637/10 "2011-10-10T14:18:15Z")

</div>

On Sat, Oct 8, 2011 at 16:19, Nikolai W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> OK, so the new interface will be
> 
> const gchar \*\*rbg\_rval2strv(volatile VALUE \*ary, long \*n);  
> #define RVAL2STRS(ary, n) rbg\_rval2strv(&(ary), &(n))
> 
> Is that fine with everyone?

This has now been implemented.
