简体   繁体   English

在方法'my_print_hexbytes'中,类型'uint32_t *'的参数1

[英]in method 'my_print_hexbytes', argument 1 of type 'uint32_t *'

I'm writing a Python C extension by SWIG but getting frustrated when passing binary buffer to C api functions. 我正在用SWIG写Python C扩展,但是在将二进制缓冲区传递给C api函数时感到沮丧。 Here's my example: 这是我的示例:

In utils.c utils.c

#include "utils.h"
void my_print_hexbytes(uint32_t *bytes, uint32_t bytes_len)
{
  uint32_t i;
  for(i = 0; i < bytes_len; i++)
    printf("%02x", bytes[i]);
  printf("\n");
}

In utils.h utils.h

#include "commons.h"
#ifndef XXXX_UTILS_H
#define XXXX_UTILS_H
void my_print_hexbytes(uint32_t *bytes, uint32_t bytes_len);
#endif /* XXXX_UTILS_H */

In commons.h commons.h

#ifndef XXXX_COMMONS_H
#define XXXX_COMMONS_H
....
....
#include <stdint.h>
....
....
#endif

In xxxx_for_py.i xxxx_for_py.i

%module xxxx_for_py
%{
#define SWIG_FILE_WITH_INIT
#include "commons.h"
#include "utils.h"
%}
%include "stdint.i"
void my_print_hexbytes(uint32_t *bytes, uint32_t bytes_len);

1st Try 第一次尝试

After compiling out _xxxx_for_py.so , I gave a try testing it in IPython: 编译_xxxx_for_py.so ,我尝试在IPython中对其进行测试:

In [1]: import xxxx_for_py

In [2]: from ctypes import *

In [3]: a_t = c_uint * 2

In [4]: a = a_t(0x1, 0x2)

In [5]: xxxx_for_py.my_print_hexbytes(a, 2)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-3c023fcf8b04> in <module>()
----> 1 xxxx_for_py.my_print_hexbytes(a, 2)

TypeError: in method 'my_print_hexbytes', argument 1 of type 'uint32_t *'

That time I had no idea how to handle this case. 那个时候我不知道该如何处理。 I tried changing the a as bytearray but it didn't work. 我尝试更改a as bytearray但是没有用。

Not sure if anyone who could help me on this issue. 不知道是否有人可以在这个问题上帮助我。 Thanks! 谢谢!

2nd Try 第二次尝试

Thanks for @Petesh comment. 感谢@Petesh评论。 I've hit a try by casting a to POINTER(c_uint) but still not work :( 我通过将aPOINTER(c_uint)了尝试,但仍然无法正常工作:(

In [5]: xxxx_for_py.my_print_hexbytes(cast(a, POINTER(c_uint)), 2)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-2abb9dae484d> in <module>()
----> 1 xxxx_for_py.my_print_hexbytes(cast(a, POINTER(c_uint)), 2)

TypeError: in method 'my_print_hexbytes', argument 1 of type 'uint32_t *'

3rd Try 第三次尝试

Referenced by Unbounded Array section in SWIG documentation, I added carray.i to xxxx_for_py.i 在SWIG文档中的“ carray.i 数组”一节中引用了我将carray.i添加到xxxx_for_py.i

In xxxx_for_py.i xxxx_for_py.i

....
....stdint.i"
%include "carrays.i"
%array_class(uint32_t, uint32Array)
....

After re-compiling and loading .so , it still got same error 重新编译并加载.so ,仍然出现相同的错误

In [1]: import xxxx_for_py

In [2]: a = xxxx_for_py.uint32Array(2)

In [3]: a[0] = 0x0

In [4]: a[1] = 0x1

In [5]: xxxx_for_py.my_print_hexbytes(a, 2)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-3c023fcf8b04> in <module>()
----> 1 xxxx_for_py.my_print_hexbytes(a, 2)

TypeError: in method 'my_print_hexbytes', argument 1 of type 'uint32_t *'

4th Try 第四次尝试

After a week later at that time, user Nethanel post an answer . 一周后的那个时候,用户Nethanel发布了答案 Though it still did not work, it could help me find something interesting. 尽管它仍然没有用,但可以帮助我找到一些有趣的东西。

After brief testing, I found solution by myself. 经过简短的测试,我自己找到了解决方案。 See this article for details http://au9ustine.github.io/wiki/crypto/cuda/swig.html#typeerror-in-method-xxxx-argument-y-of-type-zzzz 有关详细信息,请参见本文http://au9ustine.github.io/wiki/crypto/cuda/swig.html#typeerror-in-method-xxxx-argument-y-of-type-zzzz ( Update on 2017-01-13 : This page is broken, I'll move that page content here) 2017年1月13日更新 :此页面已损坏,我将在此处移动该页面的内容)

A brief anatomy 简要解剖

Keeping trying on testing Python codes on passing binary buffer to a trivial C module (ie library compiled by gcc without extra dependencies). 继续尝试通过将二进制缓冲区传递给普通的C模块(即,由gcc编译的库而没有额外的依赖关系)来测试Python代码。 And internals might look like: 内部可能看起来像:

integer list -> array/struct -> raw string -> C function parameter

From some descriptions from create_string_buffer . create_string_buffer的一些描述中。 By create_string_buffer , Python could provide such a feature dynamically allocating pieces of memory for current variables for use. 通过create_string_buffer ,Python可以提供这样的功能,即动态分配内存供当前变量使用。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

size_t
print_int_buf(void *src, size_t len)
{
    size_t i = 0;
    uint32_t *int_ptr = (uint32_t *)src;
    for (i = 0; i < len; i++) {
        printf("%p: %x\n", int_ptr + i, int_ptr[i]);
    }
    return i;
}

If compiled as a shared library named my_ext_lib.so , the code could be loaded in Python 如果编译为名为my_ext_lib.so的共享库,则可以在Python中加载代码

import ctypes
from ctypes import *
import array

my_ext = ctypes.CDLL('./my_ext_lib.so')
buf = create_string_buffer(array.array('I', range(0x10)).tostring())
my_ext_lib.print_int_buf(buf, 0x10)

And it did work. 它确实起作用。

Though ctype and SWIG are quite different approaches for interoperating integration between Python and C, I use ctype code here to elaborate the basic mechanism and its working way of passing parameters to a compiled module (both for Python module and trivial C shared library module). 尽管ctypeSWIG是用于在Python和C之间进行互操作集成的完全不同的方法,但是我在这里使用ctype代码来详细说明将参数传递给已编译模块的基本机制及其工作方式(适用于Python模块和琐碎的C共享库模块)。

Interim solution 临时解决方案

Since the significant difference was the function interface (or method signature) from my view, why not change it to void * instead of uint32_t * ? 由于我认为最大的区别是函数接口(或方法签名),为什么不将其更改为void *而不是uint32_t * (Though it's not the best way, it could be still an interim solution for containment) (尽管这不是最好的方法,但它仍然可能是临时的遏制解决方案)

I replaced uint32_t * with void * for the method my_print_hexbytes , and appended dependency cdata.i (I'm not sure if it works but for safety it has been added). 我将my_print_hexbytes方法的uint32_t *替换为void * ,并附加了依赖项cdata.i (我不确定它是否有效,但出于安全考虑已添加了它)。 So the changes were listed below and eventually it displayed expected result. 因此,更改在下面列出,最终显示了预期的结果。

utils.c

#include "utils.h"
...
void 
my_print_hexbytes(void *bytes, size_t bytes_len)
{
  size_t i = 0;
  uint32_t *int_buf_ptr = (uint32_t *)bytes;
  for(i = 0; i < bytes_len; i++)
    printf("%02x", int_buf_ptr[i]);
  printf("\n");
}

header utils.h 头文件utils.h

#include "commons.h"
#ifndef XXXX_UTILS_H
#define XXXX_UTILS_H
...
void my_print_hexbytes(void *bytes, size_t bytes_len);
#endif /* XXXX_UTILS_H */

xxxx_for_py.i

%module xxxx_for_py
%{
#define SWIG_FILE_WITH_INIT
#include "commons.h"
#include "utils.h"
%}
%include "stdint.i"
%include "carrays.i"
%include "cdata.i"
%array_class(uint32_t, uint32Array)
...
void my_print_hexbytes(void *bytes, size_t bytes_len);

Invoking method in Python, it would be like: 在Python中调用方法,就像:

In [1]: import xxxx_for_py

In [2]: a = xxxx_for_py.uint32Array(0x10)

In [3]: for i in range(0x10):
   ...:     a[i] = i
   ...:

In [4]: xxxx_for_py.my_print_hexbytes(a, 0x10)
000102030405060708090a0b0c0d0e0f

Found you question, because of same problem. 发现您的问题,因为同样的问题。

Unfortunately, it seems advanced types are not supported by SWIG: in http://www.swig.org/Doc3.0/Library.html#Library_carrays , after description of array_class macro, it is written: "When using this macro, type is restricted to a simple type name like int or float." 不幸的是,SWIG似乎不支持高级类型:在http://www.swig.org/Doc3.0/Library.html#Library_carrays中 ,在对array_class宏进行描述之后,其写道:“使用此宏时,键入只能使用简单的类型名称,例如int或float。”

I also tried unsuccessfully to use "unsigned int". 我也尝试使用“ unsigned int”失败。

In the end my workaround was to use C++ vectors instead of uint32_t pointers, here is relevant part of swig file: 最后,我的解决方法是使用C ++向量而不是uint32_t指针,这是swig文件的相关部分:

%include "stdint.i"
%include "std_vector.i"

namespace std {
   %template(vectoruint32) vector<uint32_t>;
};

part of h file: h文件的一部分:

#include <vector>

static uint32_t foo(std::vector<uint32_t> v) {return v[1] - v[0];}

python: 蟒蛇:

import example
l = [1, 2, 3, 4]
example.foo(l)

Hope this helps 希望这可以帮助

I had a very simple case but still got this error. 我有一个非常简单的案例,但仍然出现此错误。 The fix from this question worked: Swig python - c++ how to use type int8_t 这个问题的解决方法有效: Swig python-C ++如何使用int8_t类型

I added %include "stdint.i" directly after the module def in the .i file 我在.i文件中的模块def之后直接添加了%include "stdint.i"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在Python中模拟uint32_t? - Emulate uint32_t in Python? swig / python检测到“ uint32_t *”类型的内存泄漏,未发现析构函数 - swig/python detected a memory leak of type 'uint32_t *', no destructor found 如何将uint32_t转换为unsigned char数组? - How to convert uint32_t to unsigned char array? 将实现特定的C ++字符与Python中的uint32_t匹配 - Match implementation specific C++ char to uint32_t cast in Python 解析python C API中的unsigned ints(uint32_t) - Parsing unsigned ints (uint32_t) in python's C api 使用 Python.h 将 uint32_t 数组传递给 Python - Passing uint32_t array to Python using Python.h Python:如何将十六进制字符转换为CType数据类型(例如,uint32_t,uint16_t等)? - Python: How Can I Convert Hexadecimal Characters to CType Data Types (e.g., uint32_t, uint16_t, etc.)? Pytss:将参数传递给 fapi_Sign() 方法 - 无效的参数类型(uint8_t const * 类型的 Fapi_Sign 参数 4) - Pytss: passing arguments to fapi_Sign() method - invalid argument type (Fapi_Sign argument 4 of type uint8_t const *) 将 uint_32t 整数转换为字节数组 - Converting uint_32t integers to byte array 值HexBytes(* hex string *)为97字节,但在使用Contract.transact()时应为32字节。 - The Value HexBytes(*hex string*) is 97 bytes but should be 32 when using Contract.transact()
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM