簡體   English   中英

在方法'my_print_hexbytes'中,類型'uint32_t *'的參數1

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

我正在用SWIG寫Python C擴展,但是在將二進制緩沖區傳遞給C api函數時感到沮喪。 這是我的示例:

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");
}

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 */

commons.h

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

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);

第一次嘗試

編譯_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 *'

那個時候我不知道該如何處理。 我嘗試更改a as bytearray但是沒有用。

不知道是否有人可以在這個問題上幫助我。 謝謝!

第二次嘗試

感謝@Petesh評論。 我通過將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 *'

第三次嘗試

在SWIG文檔中的“ carray.i 數組”一節中引用了我將carray.i添加到xxxx_for_py.i

xxxx_for_py.i

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

重新編譯並加載.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 *'

第四次嘗試

一周后的那個時候,用戶Nethanel發布了答案 盡管它仍然沒有用,但可以幫助我找到一些有趣的東西。

經過簡短的測試,我自己找到了解決方案。 有關詳細信息,請參見本文http://au9ustine.github.io/wiki/crypto/cuda/swig.html#typeerror-in-method-xxxx-argument-y-of-type-zzzz 2017年1月13日更新 :此頁面已損壞,我將在此處移動該頁面的內容)

簡要解剖

繼續嘗試通過將二進制緩沖區傳遞給普通的C模塊(即,由gcc編譯的庫而沒有額外的依賴關系)來測試Python代碼。 內部可能看起來像:

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

create_string_buffer的一些描述中。 通過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;
}

如果編譯為名為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)

它確實起作用。

盡管ctypeSWIG是用於在Python和C之間進行互操作集成的完全不同的方法,但是我在這里使用ctype代碼來詳細說明將參數傳遞給已編譯模塊的基本機制及其工作方式(適用於Python模塊和瑣碎的C共享庫模塊)。

臨時解決方案

由於我認為最大的區別是函數接口(或方法簽名),為什么不將其更改為void *而不是uint32_t * (盡管這不是最好的方法,但它仍然可能是臨時的遏制解決方案)

我將my_print_hexbytes方法的uint32_t *替換為void * ,並附加了依賴項cdata.i (我不確定它是否有效,但出於安全考慮已添加了它)。 因此,更改在下面列出,最終顯示了預期的結果。

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");
}

頭文件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);

在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

發現您的問題,因為同樣的問題。

不幸的是,SWIG似乎不支持高級類型:在http://www.swig.org/Doc3.0/Library.html#Library_carrays中 ,在對array_class宏進行描述之后,其寫道:“使用此宏時,鍵入只能使用簡單的類型名稱,例如int或float。”

我也嘗試使用“ unsigned int”失敗。

最后,我的解決方法是使用C ++向量而不是uint32_t指針,這是swig文件的相關部分:

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

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

h文件的一部分:

#include <vector>

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

蟒蛇:

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

希望這可以幫助

我有一個非常簡單的案例,但仍然出現此錯誤。 這個問題的解決方法有效: Swig python-C ++如何使用int8_t類型

我在.i文件中的模塊def之后直接添加了%include "stdint.i"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM