簡體   English   中英

如何將具有 0 值字節的 char * 轉換為 python 字符串?

[英]How do you convert a char * with 0-value bytes into a python string?

使用 ctypes 模塊,我可以輕松地將 POINTER(c_char) 或 c_char_p 類型導入到 python 中,但這些都無法提供以包含零值字節的 python 字符串結束的方法。

c_char_p 以零終止,這意味着來自 C 的 char * 數組在第一個零值處終止。

POINTER(c_char) 是導入可以具有 0 值的二進制數據的推薦方法,但似乎沒有辦法將其直接轉換為 python 字符串。

我可以做這個:

pixels = clibblah.get_pixels()
a = ""
for i in range(0, clibblah.get_pixel_length()):
    a += pixels[i]

...但是這 1) 似乎不是很 pythony,並且 2) 需要永遠(在我的 mac 上轉換 640x480 像素數據塊大約需要 2 秒)。

我在堆棧溢出上看到了很多關於這個的問題,但是如果我看到一個不是任何人都在說“你為什么需要這樣做?” 或者“c_char_p 會做你想做的事”(它不會,正如我上面所描述的)。

我看到的唯一可靠的建議是使用 c api PyString_FromStringAndSize,如這里推薦的那樣: http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/version/Doc/FAQ.html

雖然無法真正看到這有什么幫助,因為 afaik 這是一個 cython 功能,而不是 python 功能。

對於感興趣的人,我需要這樣做的原因是我正在使用 panda3d 和 kinect,而 kinect c api 提供了一個 unsigned char * 值數組,而 panda3d api 親切地提供了一個 setPixels() 調用,它只需要一個python 字符串作為參數。

如您所說,使用POINTER(c_char)獲取指向二進制數據數組的指針。 要將它們組合成一個字符串,您可以只取它的一部分,因為數組索引按預期使用 ctypes 指針工作:

clibblah = ctypes.cdll.LoadLibrary('clibblah.dylib')
get_pixels = clibblah.get_pixels
get_pixels.restype = ctypes.POINTER(ctypes.c_char)

pixels = get_pixels()
num_pixels = clibblah.get_pixel_length()

# Slice the ctypes array into a Python string
a = pixels[:num_pixels]

有幾種不同的方法。 我喜歡ctypes.string_at ,因為它不挑剔:無論您提供的是c_char_p類型、指向c_char的指針、void 指針類型,還是只是一個int地址,它都能正常工作。

s = b'hello\x00world' # create a string containing null bytes
sz = len(s)
from ctypes import *

p = c_char_p(s) # obtain a pointer of various types
p2 = cast(p,POINTER(c_char))
address = cast(p,c_void_p).value

print p.value # by default it is interpreted as null-terminated

print p2[:sz] # various methods of explicitly specifying the full length
print string_at(p,size=sz)
print (c_char * sz).from_address(address).raw

我不知道主要問題的最佳答案是什么,但這里有一些關於如何使用PyString_FromStringAndSize來完成你想要的事情的評論。

PyString_FromStringAndSize是 Python C API: http://docs.python.org/c-api/string.html的一部分

這意味着您可以使用它來

  • 在 C/C++ 中編寫一個 Python 模塊,您在其中定義一個新的 Python 數據類型您的 C 派生字符串和空字符
  • 您可以定義該數據類型,以便它提供一個 Python 構造函數,該構造函數接受 arguments 以某種方式包含指向相關 C 字符串的指針。 如果沒有任何幫助,構造函數接受的參數可能是來自c_void_p的 c_void_p。
  • 您定義的構造函數(在 C/C++ 中)必須將指向 C 字符串的指針存儲在成員變量中。 它還可能進行復制和/或增加引用計數等。由於構造函數是用 C/C++ 編寫的,因此該構造函數中可能存在任何可能。

您必須將其構建到 a.dll/.pyd 庫中,然后才能import其導入任何 Python 代碼中。

不可否認,這是一個相當復雜的過程。 希望其他人建議一種更簡單的方法,也許直接基於 ctypes。

暫無
暫無

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

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