我正在使用swig生成一些从c到ruby的包装器。
一些函数希望我传入一个将更新的char *。
例如:
void setvarc(int arg1, char * arg2);
我认为在将与函数接口的ruby类中,我可以使用String.new来创建一个足以容纳数据的字符串,然后将其传递给函数。
这样的事情:
return_string = " " * 10
setvarc(arg1, return_string)
但这不是一个非常好的解决方案,并且非常像非红宝石。
我在swig手册的第9章中看到如何使用类型映射来处理参数但不分配空间。 我想我需要围绕这个函数创建一个小的c包装并分配空间,但是我必须在返回后清理它。 Swig似乎也有一些可以处理的类型图,但这并不是一个很好的例子来说明这一点。
这似乎是经常出现的事情。
我认为它应该是这样的。
(我的c生锈了所以这可能是错的,但你明白了)
char * get_value(int arg1) {
char * buffer = malloc(some_number);
setvarc(arg1,buffer);
return buffer
}
然后是一些swig类型图,希望能让ruby获取新字符串的副本并释放空间。
有没有人有一个如何将这一切联系在一起的例子?
答案 0 :(得分:1)
你应该能够逃脱:
%ignore setvarc;
%newobject get_value;
%inline %{
char* get_value(int argc)
{
char * buffer = malloc(some_number);
setvarc(arg1,buffer);
return buffer;
}
%}
SWIG应将get_value包装为Ruby字符串,并取得函数分配的内存的所有权(因为%newobject)。
答案 1 :(得分:0)
更新:虽然这很好用但接受的答案有点清洁
我想通了,如果有人需要它,这是一个例子:
/* set a type map for the next set of functions */
/* it just needs to match any arg so it will get triggered */
%typemap(freearg) char {
free(result);
}
/* create a simple interface that will allocate the required space */
char *get_value(FACREF *facref, char mode);
%inline %{
char *get_value(FACREF *facref, char mode) {
int fac_size = facref->length + 1;
char *result = (char *) malloc((sizeof(char) * fac_size) + 1);
setvarc(facref, result, mode);
return result;
}
%}
/* clear the typemap when done */
%typemap(in) char;
然后swig用这段代码包装。
SWIGINTERN VALUE
_wrap_get_value(int argc, VALUE *argv, VALUE self) {
FACREF *arg1 = (FACREF *) 0 ;
char arg2 ;
void *argp1 = 0 ;
int res1 = 0 ;
char val2 ;
int ecode2 = 0 ;
char *result = 0 ;
VALUE vresult = Qnil;
if ((argc < 2) || (argc > 2)) {
rb_raise(rb_eArgError, "wrong # of arguments(%d for 2)",argc); SWIG_fail;
}
res1 = SWIG_ConvertPtr(argv[0], &argp1,SWIGTYPE_p_facref, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), Ruby_Format_TypeError( "", "FACREF *","get_value", 1, argv[0] ));
}
arg1 = (FACREF *)(argp1);
ecode2 = SWIG_AsVal_char(argv[1], &val2);
if (!SWIG_IsOK(ecode2)) {
SWIG_exception_fail(SWIG_ArgError(ecode2), Ruby_Format_TypeError( "", "char","get_value", 2, argv[1] ));
}
arg2 = (char)(val2);
result = (char *)get_value(arg1,arg2);
vresult = SWIG_FromCharPtr((const char *)result);
{
free(result);
}
return vresult;
fail:
{
free(result);
}
return Qnil;
}