6

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)あまりパイソンではないようで、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

ただし、これがどのように役立つかはわかりません。これは、Pythonの機能ではなくcythonの機能であるafaikだからです。

興味があるので、これを行う必要がある理由は、panda3dとkinectを使用しているためです。また、kinectcapiはunsignedchar*値の配列を提供し、panda3d apiは愛情を込めてsetPixels()呼び出しを提供します。引数としてのPython文字列。

4

3 に答える 3

7

あなたが言ったよう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]
于 2012-04-11T03:01:08.073 に答える
7

いくつかの異なる方法があります。私ctypes.string_atはそれが気難しいものではないので好きです:それはあなたがc_char_pタイプ、またはポインタへのポインタc_char、またはボイドポインタタイプ、あるいは単に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
于 2016-08-02T02:40:49.443 に答える
1

主な質問に対する最良の答えが何であるかはわかりませんが、ここに、PyString_FromStringAndSizeあなたが望むことを達成するためにどのように使用できるかについてのいくつかのコメントがあります。

PyString_FromStringAndSizePython C APIの一部です:http://docs.python.org/c-api/string.html

つまり、これを使用して

  • 新しいPythonデータ型を定義するC/C++でPythonモジュールを記述します。Cから派生したstrings-with-null-characters
  • そのデータ型を定義して、問題のC文字列へのポインターを何らかの形で含む引数を受け入れるPythonコンストラクターを提供することができます。何も役に立たない場合、コンストラクターが受け入れる引数はc_void_pcytpesからのものである可能性があります。
  • (C / C ++で)定義するコンストラクターは、C文字列へのポインターをメンバー変数に格納する必要があります。また、コピーを作成したり、参照数を増やしたりする場合もあります。コンストラクターはC / C ++で記述されているため、そのコンストラクターで可能なことはすべて可能です。

これを.dll/.pydライブラリにビルドしてから、import任意のPythonコードにビルドする必要があります。

確かに、かなり複雑な手順です。うまくいけば、他の誰かが、おそらくctypesに直接基づいて、より簡単な方法を提案します。

于 2012-04-11T02:46:11.283 に答える