sfcc 0.1.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,6 +7,6 @@
7
7
  void init_cim_string();
8
8
 
9
9
  extern VALUE cSfccCimString;
10
- VALUE Sfcc_wrap_cim_string(CMPIString *string);
10
+ VALUE Sfcc_wrap_cim_string(CIMCString *string);
11
11
 
12
12
  #endif
@@ -1,8 +1,12 @@
1
1
  require 'mkmf'
2
2
  # $CFLAGS = "#{$CFLAGS} -Werror"
3
3
 
4
- have_library('cmpisfcc', 'NewCIMCEnv')
5
- #find_header 'cimc.h', '/usr/include/cimc'
6
- find_header 'cmci.h', '/usr/include/CimClientLib'
7
- create_makefile('sfcc')
4
+ unless have_library('cimcclient', 'NewCIMCEnv')
5
+ STDERR.puts "Cannot find NewCIMCEnv() in libcimcclient"
6
+ STDERR.puts "Is sblim-sfcc-devel installed ?"
7
+ exit 1
8
+ end
8
9
 
10
+ find_header 'cimc.h', '/usr/include/cimc'
11
+ find_header 'cmcimacs.h', '/usr/include/CimClientLib'
12
+ create_makefile('sfcc')
@@ -3,10 +3,6 @@
3
3
 
4
4
  #include "sfcc.h"
5
5
 
6
- #include <CimClientLib/cmci.h>
7
- #include <CimClientLib/native.h>
8
- #include <CimClientLib/cmcimacs.h>
9
-
10
6
  #include "cim_string.h"
11
7
  #include "cim_object_path.h"
12
8
  #include "cim_enumeration.h"
@@ -16,9 +12,23 @@
16
12
 
17
13
  VALUE mSfcc;
18
14
  VALUE mSfccCim;
15
+ CIMCEnv *cimcEnv;
16
+
17
+ static void
18
+ Exit_sfcc(CIMCEnv *env)
19
+ {
20
+ /* fprintf(stderr, "Sfcc_dealloc_cimcEnv %p\n", env); */
21
+ if (env) env->ft->release(env);
22
+ }
19
23
 
20
24
  void Init_sfcc()
21
25
  {
26
+ const char *conn;
27
+ VALUE cEnvironment; /* class */
28
+ VALUE value; /* wrapped value */
29
+ int rc;
30
+ char *msg;
31
+
22
32
  /**
23
33
  * SBLIM sfcc ruby API
24
34
  */
@@ -28,6 +38,22 @@ void Init_sfcc()
28
38
  */
29
39
  mSfccCim= rb_define_module_under(mSfcc, "Cim");
30
40
 
41
+ /**
42
+ * alloc CimcEnvironment once, store as const
43
+ */
44
+ cEnvironment = rb_define_class_under(mSfccCim, "CimcEnvironment", rb_cObject);
45
+ conn = getenv("RUBY_SFCC_CONNECTION"); /* "SfcbLocal" or "XML" */
46
+ if (!conn) conn = "XML";
47
+ cimcEnv = NewCIMCEnv(conn,0,&rc,&msg);
48
+ if (!cimcEnv) {
49
+ rb_raise(rb_eLoadError, "Cannot local %s cim client library. %d:%s", conn, rc, msg ? msg : "");
50
+ }
51
+ value = Data_Wrap_Struct(cEnvironment, NULL, Exit_sfcc, cimcEnv);
52
+ rb_define_const(mSfccCim, "CIMC_ENV", value);
53
+
54
+ /**
55
+ * Init other sub-classes
56
+ */
31
57
  init_cim_string();
32
58
  init_cim_object_path();
33
59
  init_cim_enumeration();
@@ -36,53 +62,53 @@ void Init_sfcc()
36
62
  init_cim_client();
37
63
  }
38
64
 
39
- static VALUE sfcc_status_exception(CMPIStatus status)
65
+ static VALUE sfcc_status_exception(CIMCStatus status)
40
66
  {
41
67
  switch (status.rc)
42
68
  {
43
- case CMPI_RC_ERR_FAILED:
69
+ case CIMC_RC_ERR_FAILED:
44
70
  return rb_const_get(mSfccCim, rb_intern("ErrorFailed"));
45
- case CMPI_RC_ERR_ACCESS_DENIED:
71
+ case CIMC_RC_ERR_ACCESS_DENIED:
46
72
  return rb_const_get(mSfccCim, rb_intern("ErrorAcessDenied"));
47
- case CMPI_RC_ERR_INVALID_NAMESPACE:
73
+ case CIMC_RC_ERR_INVALID_NAMESPACE:
48
74
  return rb_const_get(mSfccCim, rb_intern("ErrorInvalidNamespace"));
49
- case CMPI_RC_ERR_INVALID_PARAMETER:
75
+ case CIMC_RC_ERR_INVALID_PARAMETER:
50
76
  return rb_const_get(mSfccCim, rb_intern("ErrorInvalidParameter"));
51
- case CMPI_RC_ERR_INVALID_CLASS:
77
+ case CIMC_RC_ERR_INVALID_CLASS:
52
78
  return rb_const_get(mSfccCim, rb_intern("ErrorInvalidClass"));
53
- case CMPI_RC_ERR_NOT_FOUND:
79
+ case CIMC_RC_ERR_NOT_FOUND:
54
80
  return rb_const_get(mSfccCim, rb_intern("ErrorNotFound"));
55
- case CMPI_RC_ERR_NOT_SUPPORTED:
81
+ case CIMC_RC_ERR_NOT_SUPPORTED:
56
82
  return rb_const_get(mSfccCim, rb_intern("ErrorNotSupported"));
57
- case CMPI_RC_ERR_CLASS_HAS_CHILDREN:
83
+ case CIMC_RC_ERR_CLASS_HAS_CHILDREN:
58
84
  return rb_const_get(mSfccCim, rb_intern("ErrorClassHasChildren"));
59
- case CMPI_RC_ERR_CLASS_HAS_INSTANCES:
85
+ case CIMC_RC_ERR_CLASS_HAS_INSTANCES:
60
86
  return rb_const_get(mSfccCim, rb_intern("ErrorClassHasInstances"));
61
- case CMPI_RC_ERR_INVALID_SUPERCLASS:
87
+ case CIMC_RC_ERR_INVALID_SUPERCLASS:
62
88
  return rb_const_get(mSfccCim, rb_intern("ErrorInvalidSuperClass"));
63
- case CMPI_RC_ERR_ALREADY_EXISTS:
89
+ case CIMC_RC_ERR_ALREADY_EXISTS:
64
90
  return rb_const_get(mSfccCim, rb_intern("ErrorAlreadyExists"));
65
- case CMPI_RC_ERR_NO_SUCH_PROPERTY:
91
+ case CIMC_RC_ERR_NO_SUCH_PROPERTY:
66
92
  return rb_const_get(mSfccCim, rb_intern("ErrorNoSuchProperty"));
67
- case CMPI_RC_ERR_TYPE_MISMATCH:
93
+ case CIMC_RC_ERR_TYPE_MISMATCH:
68
94
  return rb_const_get(mSfccCim, rb_intern("ErrorTypeMismatch"));
69
- case CMPI_RC_ERR_QUERY_LANGUAGE_NOT_SUPPORTED:
95
+ case CIMC_RC_ERR_QUERY_LANGUAGE_NOT_SUPPORTED:
70
96
  return rb_const_get(mSfccCim, rb_intern("ErrorQueryLanguageNotSupported"));
71
- case CMPI_RC_ERR_INVALID_QUERY:
97
+ case CIMC_RC_ERR_INVALID_QUERY:
72
98
  return rb_const_get(mSfccCim, rb_intern("ErrorInvalidQuery"));
73
- case CMPI_RC_ERR_METHOD_NOT_AVAILABLE:
99
+ case CIMC_RC_ERR_METHOD_NOT_AVAILABLE:
74
100
  return rb_const_get(mSfccCim, rb_intern("ErrorMethodNotAvailable"));
75
- case CMPI_RC_ERR_METHOD_NOT_FOUND:
101
+ case CIMC_RC_ERR_METHOD_NOT_FOUND:
76
102
  return rb_const_get(mSfccCim, rb_intern("ErrorMethodNotFound"));
77
- case CMPI_RC_DO_NOT_UNLOAD:
103
+ case CIMC_RC_DO_NOT_UNLOAD:
78
104
  return rb_const_get(mSfccCim, rb_intern("ErrorDoNotUnload"));
79
- case CMPI_RC_NEVER_UNLOAD:
105
+ case CIMC_RC_NEVER_UNLOAD:
80
106
  return rb_const_get(mSfccCim, rb_intern("ErrorNeverUnload"));
81
- case CMPI_RC_ERROR_SYSTEM:
107
+ case CIMC_RC_ERROR_SYSTEM:
82
108
  return rb_const_get(mSfccCim, rb_intern("ErrorSystem"));
83
- case CMPI_RC_ERROR:
109
+ case CIMC_RC_ERROR:
84
110
  return rb_const_get(mSfccCim, rb_intern("ErrorRcError"));
85
- case CMPI_RC_OK:
111
+ case CIMC_RC_OK:
86
112
  default:
87
113
  return Qnil;
88
114
  }
@@ -90,7 +116,7 @@ static VALUE sfcc_status_exception(CMPIStatus status)
90
116
 
91
117
  #define MAX_ERROR_BUFFER 255
92
118
 
93
- void sfcc_rb_raise_if_error(CMPIStatus status, const char *msg, ...)
119
+ void sfcc_rb_raise_if_error(CIMCStatus status, const char *msg, ...)
94
120
  {
95
121
  va_list arg_list;
96
122
  char orig_error[MAX_ERROR_BUFFER];
@@ -103,8 +129,10 @@ void sfcc_rb_raise_if_error(CMPIStatus status, const char *msg, ...)
103
129
  vsnprintf(orig_error, MAX_ERROR_BUFFER, msg, arg_list);
104
130
  va_end(arg_list);
105
131
 
106
- if (status.msg)
132
+ if (status.msg) {
107
133
  snprintf(error, MAX_ERROR_BUFFER, "%s : %s", orig_error, status.msg->ft->getCharPtr(status.msg, NULL));
134
+ CMRelease(status.msg);
135
+ }
108
136
  else
109
137
  strcpy(error, orig_error);
110
138
 
@@ -119,7 +147,7 @@ char ** sfcc_value_array_to_string_array(VALUE array)
119
147
  if ( !NIL_P(array) && RARRAY_LEN(array) > 0 ) {
120
148
  ret = (char**) malloc(RARRAY_LEN(array)*sizeof(char*));
121
149
  for (; i < RARRAY_LEN(array); ++i)
122
- ret[i] = StringValuePtr(*(RARRAY_PTR(array) + i));
150
+ ret[i] = (char *)to_charptr(*(RARRAY_PTR(array) + i));
123
151
  }
124
152
  else
125
153
  ret = NULL;
@@ -127,13 +155,13 @@ char ** sfcc_value_array_to_string_array(VALUE array)
127
155
  return ret;
128
156
  }
129
157
 
130
- VALUE sfcc_cimdata_to_value(CMPIData data)
158
+ VALUE sfcc_cimdata_to_value(CIMCData data)
131
159
  {
132
- CMPIString *cimstr = NULL;
160
+ CIMCString *cimstr = NULL;
133
161
  VALUE rbval;
134
- CMPIStatus status;
162
+ CIMCStatus status;
135
163
 
136
- if (data.type & CMPI_ARRAY) {
164
+ if (data.type & CIMC_ARRAY) {
137
165
  int k = 0;
138
166
  int n = 0;
139
167
  VALUE rbarray = rb_ary_new();
@@ -144,7 +172,7 @@ VALUE sfcc_cimdata_to_value(CMPIData data)
144
172
  n = data.value.array->ft->getSize(data.value.array, &status);
145
173
  if (!status.rc) {
146
174
  for (k = 0; k < n; ++k) {
147
- CMPIData element = data.value.array->ft->getElementAt(data.value.array, k, NULL);
175
+ CIMCData element = data.value.array->ft->getElementAt(data.value.array, k, NULL);
148
176
  rb_ary_push(rbarray, sfcc_cimdata_to_value(element));
149
177
  }
150
178
  return rbarray;
@@ -152,59 +180,64 @@ VALUE sfcc_cimdata_to_value(CMPIData data)
152
180
  sfcc_rb_raise_if_error(status, "Can't retrieve array size");
153
181
  return Qnil;
154
182
  }
155
- else if (data.type & CMPI_ENC) {
183
+ else if (data.type & CIMC_ENC) {
156
184
  switch (data.type) {
157
- case CMPI_instance:
185
+ case CIMC_instance:
158
186
  return data.value.inst ? Sfcc_wrap_cim_instance(data.value.inst->ft->clone(data.value.inst, NULL)) : Qnil;
159
- case CMPI_class:
187
+ case CIMC_class:
160
188
  return data.value.cls ? Sfcc_wrap_cim_class(data.value.cls->ft->clone(data.value.cls, NULL)) : Qnil;
161
- case CMPI_ref:
189
+ case CIMC_ref:
162
190
  return data.value.ref ? Sfcc_wrap_cim_object_path(data.value.ref->ft->clone(data.value.ref, NULL)) : Qnil;
163
- case CMPI_args:
191
+ case CIMC_args:
164
192
  return data.value.args ? sfcc_cimargs_to_hash(data.value.args) : Qnil;
165
- case CMPI_filter:
193
+ case CIMC_filter:
166
194
  return Qnil;
167
- case CMPI_numericString:
168
- case CMPI_booleanString:
169
- case CMPI_dateTimeString:
170
- case CMPI_classNameString:
195
+ case CIMC_numericString:
196
+ case CIMC_booleanString:
197
+ case CIMC_dateTimeString:
198
+ case CIMC_classNameString:
171
199
  break;
172
- case CMPI_string:
200
+ case CIMC_string:
173
201
  return data.value.string ? rb_str_new2((char*)data.value.string->ft->getCharPtr(data.value.string, NULL)) : Qnil;
174
- case CMPI_charsptr:
202
+ case CIMC_charsptr:
175
203
  return data.value.chars ? rb_str_new((char*)data.value.dataPtr.ptr, data.value.dataPtr.length) : Qnil;
176
- case CMPI_dateTime:
177
- cimstr = data.value.dateTime ? CMGetStringFormat(data.value.dateTime,NULL) : NULL;
178
- rbval = cimstr ? rb_str_new2(cimstr->ft->getCharPtr(cimstr, NULL)) : Qnil;
179
- if (cimstr) CMRelease(cimstr);
204
+ case CIMC_dateTime:
205
+ if (data.value.dateTime) {
206
+ CIMCUint64 bintime;
207
+ bintime = data.value.dateTime->ft->getBinaryFormat(data.value.dateTime, NULL);
208
+ rbval = rb_time_new((time_t) (bintime / 1000000L), (time_t) (bintime % 1000000));
209
+ }
210
+ else {
211
+ rbval = Qnil;
212
+ }
180
213
  return rbval;
181
214
  }
182
215
  }
183
- else if (data.type & CMPI_SIMPLE) {
216
+ else if (data.type & CIMC_SIMPLE) {
184
217
  switch (data.type) {
185
- case CMPI_boolean: return data.value.boolean ? Qtrue : Qfalse;
186
- case CMPI_char16: return UINT2NUM(data.value.char16);
218
+ case CIMC_boolean: return data.value.boolean ? Qtrue : Qfalse;
219
+ case CIMC_char16: return UINT2NUM(data.value.char16);
187
220
  }
188
221
  }
189
- else if (data.type & CMPI_INTEGER) {
222
+ else if (data.type & CIMC_INTEGER) {
190
223
  switch (data.type) {
191
- case CMPI_uint8: return UINT2NUM(data.value.uint8);
192
- case CMPI_sint8: return INT2NUM(data.value.sint8);
193
- case CMPI_uint16: return UINT2NUM(data.value.uint16);
194
- case CMPI_sint16: return INT2NUM(data.value.sint16);
195
- case CMPI_uint32: return UINT2NUM(data.value.uint32);
196
- case CMPI_sint32: return INT2NUM(data.value.sint32);
197
- case CMPI_uint64: return UINT2NUM(data.value.uint64);
198
- case CMPI_sint64: return INT2NUM(data.value.sint64);
224
+ case CIMC_uint8: return UINT2NUM(data.value.uint8);
225
+ case CIMC_sint8: return INT2NUM(data.value.sint8);
226
+ case CIMC_uint16: return UINT2NUM(data.value.uint16);
227
+ case CIMC_sint16: return INT2NUM(data.value.sint16);
228
+ case CIMC_uint32: return UINT2NUM(data.value.uint32);
229
+ case CIMC_sint32: return INT2NUM(data.value.sint32);
230
+ case CIMC_uint64: return UINT2NUM(data.value.uint64);
231
+ case CIMC_sint64: return INT2NUM(data.value.sint64);
199
232
  }
200
233
  }
201
- else if (data.type & CMPI_REAL) {
234
+ else if (data.type & CIMC_REAL) {
202
235
  switch (data.type) {
203
- case CMPI_real32: return LONG2NUM(data.value.real32);
204
- case CMPI_real64: return LONG2NUM(data.value.real64);
236
+ case CIMC_real32: return rb_float_new(data.value.real32);
237
+ case CIMC_real64: return rb_float_new(data.value.real64);
205
238
  }
206
239
  }
207
- else if (data.type & CMPI_null ) {
240
+ else if (data.type & CIMC_null ) {
208
241
  return Qnil;
209
242
  }
210
243
  rb_raise(rb_eTypeError, "unsupported data data type %d", data.type);
@@ -214,11 +247,11 @@ VALUE sfcc_cimdata_to_value(CMPIData data)
214
247
  /* callback to add each hash element to a CMPIArgs */
215
248
  static int hash_to_cimargs_iterator(VALUE key, VALUE value, VALUE extra)
216
249
  {
217
- CMPIStatus status;
218
- CMPIData data;
219
- CMPIArgs *args = (CMPIArgs *)extra;
250
+ CIMCStatus status;
251
+ CIMCData data;
252
+ CIMCArgs *args = (CIMCArgs *)extra;
220
253
  VALUE key_str = rb_funcall(key, rb_intern("to_s"), 0);
221
- char *key_cstr = StringValuePtr(key_str);
254
+ const char *key_cstr = to_charptr(key_str);
222
255
  data = sfcc_value_to_cimdata(value);
223
256
  status = args->ft->addArg(args, key_cstr, &data.value, data.type);
224
257
 
@@ -226,42 +259,40 @@ static int hash_to_cimargs_iterator(VALUE key, VALUE value, VALUE extra)
226
259
  return ST_CONTINUE;
227
260
  }
228
261
 
229
- sfcc_rb_raise_if_error(status, "Can't add argument '%s'", StringValuePtr(key));
262
+ sfcc_rb_raise_if_error(status, "Can't add argument '%s'", to_charptr(key));
230
263
  return ST_STOP;
231
264
  }
232
265
 
233
- CMPIArgs *sfcc_hash_to_cimargs(VALUE hash)
266
+ CIMCArgs *sfcc_hash_to_cimargs(VALUE hash)
234
267
  {
235
- CMPIArgs *args;
236
- args = newCMPIArgs(NULL);
268
+ CIMCArgs *args;
269
+ args = cimcEnv->ft->newArgs(cimcEnv, NULL);
237
270
  rb_hash_foreach(hash, hash_to_cimargs_iterator, (VALUE)args);
238
271
  return args;
239
272
  }
240
273
 
241
- VALUE sfcc_cimargs_to_hash(CMPIArgs *args)
274
+ VALUE sfcc_cimargs_to_hash(CIMCArgs *args)
242
275
  {
243
- CMPIArgs *ptr = NULL;
244
276
  int i = 0;
245
277
  int n = 0;
246
278
  VALUE hash;
247
- CMPIString *argname;
248
- CMPIData argdata;
249
- CMPIStatus status;
279
+ CIMCString *argname;
280
+ CIMCData argdata;
281
+ CIMCStatus status;
250
282
  char *argname_cstr = NULL;
251
283
 
252
- //Data_Get_Struct(args, CMPIArgs, ptr);
253
- ptr = args;
254
- if (!ptr) {
284
+ /* Data_Get_Struct(value, CIMCArgs, args); */
285
+ if (!args) {
255
286
  rb_raise(rb_eRuntimeError, "Can't retrieve args pointer");
256
287
  return Qnil;
257
288
  }
258
- n = ptr->ft->getArgCount(ptr, NULL);
289
+ n = args->ft->getArgCount(args, NULL);
259
290
  hash = rb_hash_new();
260
291
 
261
292
  for (; i < n; ++i) {
262
293
  argname = NULL;
263
- argdata = ptr->ft->getArgAt(ptr, i, &argname, &status);
264
- if (!status.rc && argdata.state == CMPI_goodValue ) {
294
+ argdata = args->ft->getArgAt(args, i, &argname, &status);
295
+ if (!status.rc && argdata.state == CIMC_goodValue ) {
265
296
  argname_cstr = argname->ft->getCharPtr(argname, &status);
266
297
  if (!argname_cstr) {
267
298
  rb_raise(rb_eRuntimeError, "Can't retrieve argument name");
@@ -284,37 +315,37 @@ VALUE sfcc_cimargs_to_hash(CMPIArgs *args)
284
315
  return hash;
285
316
  }
286
317
 
287
- CMPIData sfcc_value_to_cimdata(VALUE value)
318
+ CIMCData sfcc_value_to_cimdata(VALUE value)
288
319
  {
289
- CMPIData data;
290
- memset(&data, 0, sizeof(CMPIData));
291
- data.state = CMPI_goodValue;
292
- data.type = CMPI_null;
320
+ CIMCData data;
321
+ memset(&data, 0, sizeof(CIMCData));
322
+ data.state = CIMC_goodValue;
323
+ data.type = CIMC_null;
293
324
 
294
325
  switch (TYPE(value))
295
326
  {
296
327
  case T_NIL:
297
- data.type = CMPI_null;
298
- data.state = CMPI_nullValue;
328
+ data.type = CIMC_null;
329
+ data.state = CIMC_nullValue;
299
330
  break;
300
331
  case T_STRING:
301
- data.type = CMPI_string;
302
- data.value.string = newCMPIString(StringValuePtr(value), NULL);
332
+ data.type = CIMC_string;
333
+ data.value.string = cimcEnv->ft->newString(cimcEnv, to_charptr(value), NULL);
303
334
  break;
304
335
  case T_TRUE:
305
- data.type = CMPI_boolean;
336
+ data.type = CIMC_boolean;
306
337
  data.value.boolean = 1;
307
338
  break;
308
339
  case T_FALSE:
309
- data.type = CMPI_boolean;
340
+ data.type = CIMC_boolean;
310
341
  data.value.boolean = 0;
311
342
  break;
312
343
  case T_FIXNUM:
313
- data.type = CMPI_sint64;
344
+ data.type = CIMC_sint64;
314
345
  data.value.Long = NUM2INT(value);
315
346
  break;
316
347
  /* not yet supported
317
- case T_BIGNUM:
348
+ case T_BIGNUM:
318
349
  break;
319
350
  case T_FLOAT:
320
351
  break;
@@ -327,17 +358,44 @@ CMPIData sfcc_value_to_cimdata(VALUE value)
327
358
  case T_DATA:
328
359
  default:
329
360
  if (CLASS_OF(value) == cSfccCimString) {
330
- Data_Get_Struct(value, CMPIString, data.value.string);
331
- data.type = CMPI_string;
361
+ Data_Get_Struct(value, CIMCString, data.value.string);
362
+ data.type = CIMC_string;
332
363
  }
333
364
  else {
334
- data.state = CMPI_badValue;
335
- data.type = CMPI_null;
336
- VALUE cname = rb_funcall(rb_funcall(value, rb_intern("class"), 0), rb_intern("to_s"), 0);
337
- const char *class_name = StringValuePtr(cname);
365
+ VALUE cname;
366
+ const char *class_name;
367
+ data.state = CIMC_badValue;
368
+ data.type = CIMC_null;
369
+ cname = rb_funcall(rb_funcall(value, rb_intern("class"), 0), rb_intern("to_s"), 0);
370
+ class_name = to_charptr(cname);
338
371
  rb_raise(rb_eTypeError, "unsupported data data type: %s", class_name);
339
372
  return data;
340
373
  }
341
374
  }
342
375
  return data;
343
376
  }
377
+
378
+ /*
379
+ * target_charptr
380
+ * Convert target type to const char *
381
+ */
382
+
383
+ const char *
384
+ to_charptr(VALUE v)
385
+ {
386
+ const char *str;
387
+ if (SYMBOL_P(v)) {
388
+ str = rb_id2name(SYM2ID(v));
389
+ }
390
+ else if (TYPE(v) == T_STRING) {
391
+ str = StringValuePtr(v);
392
+ }
393
+ else if (v == Qnil) {
394
+ str = NULL;
395
+ }
396
+ else {
397
+ VALUE v_s = rb_funcall(v, rb_intern("to_s"), 0 );
398
+ str = StringValuePtr(v_s);
399
+ }
400
+ return str;
401
+ }