sfcc 0.1.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ }