我正在使用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'指针,而是指向自定义结构的指针
答案 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*};
但我从未使用过这些。