如何告诉Swig将'u_char *'视为'unsigned char *'

时间:2014-01-20 17:13:33

标签: c swig unsigned-char

我正在使用Swig包装C库,以便能够在PHP中使用它。该库使用u_char *代替unsigned char *。 Swig将u_char视为一个它不知道的结构。

这会导致生成的代码检查参数类型,当我将字符串作为char *数据传递时,这显然会失败。

如何告诉Swig u_char指针只是unsigned char指针?

即。这个C函数

int c_library_function(u_char *data, size_t data_size);

在生成的代码中进行了此检查:

if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_unsigned_char, 0) < 0) {
  SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of c_library_function. Expected SWIGTYPE_p_unsigned_char");
}

失败的地方。

我尝试将%typemap(ctype) u_char "unsigned char"添加到Swig模板中,似乎没有效果。

编辑 为了澄清一件事,u_char肯定是一个无符号字符。库中的C文件包括sys/types.h,其中包含bits/types.h,其中包含条目:

typedef unsigned char __u_char;

另外,只需编写一个函数来包装对C函数的调用,以便能够转换类型,按预期工作:

void libraryFunction(u_char *foo) {
    //Does stuff with foo
}

void castLibraryFunction(char *foo) {
     libraryFunction((u_char *)foo);
}

但我不想为每个需要u_char *参数的函数编写包装器。

更明显的是,Swig检查的类型是SWIGTYPE_p_unsigned_char,即它理解数据类型是'unsigned char'但不使用'unsigned char'指针,而是指向自定义结构的指针

1 个答案:

答案 0 :(得分:1)

根据Is u_char a standard?,u_char相当于uint8_t(C99),而不是unsigned char。因此,如果你有一个从PHP接收的unsigned char数组,你必须将chars复制到一个新的uint8_t(u_char)数组中,调用你的lib的C函数,如果它修改了数据(因为它需要一个u_char) *不是const uchar *)你必须将结果复制到原始数组中,以便PHP看到更改。如果PHP使用不可变字符串,则必须返回字符串。

SWIG可以帮助完成上述某些任务(例如通过%inline和%extend;我认为你不需要类型映射)。

如果u_char确实是一个unsigned char,并且PHP给你一个char *,那么原理是相同的,但你不需要复制部分,因为size类型与char *相同。您可以使用%inline:

%inline %{
    int c_library_function(char* phpString, size_t stringSize) {
          return c_library_function((u_char*) phpString, stringSize);
    }
%}

如果您不想为每个需要u_char *的函数执行此操作,我认为您唯一的选择是.i文件中的typemap条目,例如

%array_class(unsigned char, char); 

%apply char*  {unsigned char*};

但我从未使用过这些。