【问题标题】:How to tell Swig to treat 'u_char *' as 'unsigned char *'如何告诉 Swig 将 'u_char *' 视为 'unsigned char *'
【发布时间】:2014-02-09 23:37:00
【问题描述】:

我正在使用 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");
}

失败的地方。

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

编辑为了澄清一件事,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”指针,而是指向自定义结构的指针。

【问题讨论】:

    标签: c swig unsigned-char


    【解决方案1】:

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

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

    如果u_char真的是一个unsigned char,而PHP给你的是一个char*,那么原理是一样的,但是你不需要复制部分,因为大小类型和char*是一样的。你可以使用 %inline:

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

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

    %array_class(unsigned char, char); 
    

    %apply char*  {unsigned char*};
    

    但我从未使用过这些。

    【讨论】:

    • 我澄清了,这绝对是无符号字符数据。在对该库的一项测试中,我尝试调用的函数传递了从文件中读取的“char *”数据,并且它被静默地转换为 u_char。
    • uint8_t 可能只是unsigned char 的类型定义。由于 typedef 只是为现有类型而不是新类型创建别名,uint8_tunsigned charu_char 很可能相同类型。 (普通的char 是一种独特的类型,可以是有符号的也可以是无符号的。)将相同数据处理为charunsigned char 的指针转换原则上是有问题的,但它们通常可以工作。
    • @KeithThompson 和 Danack 该技术仍然适用,只是不需要复制部分。已编辑。
    • 谢谢 - 它显示为“%apply char* {unsigned char*};”是告诉 Swig 做正确事情的人。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多