4

tl; dr

これは、GNUバージョンのlibcで動作します(uclibcではまだ試していません)

from ctypes import *

libc = CDLL('libc.so.6')

class uts_struct(Structure):
    _fields_ = [ ('sysname', c_char * 65),
                 ('nodename', c_char * 65),
                 ('release', c_char * 65),
                 ('version', c_char * 65),
                 ('machine', c_char * 65),
                 ('domain', c_char * 65) ]

gnar = uts_struct()

libc.uname(byref(gnar))

print gnar.nodename

元の投稿

次のコードはsegfaultsです。何が間違っているのかわかりません。

from ctypes import *

libc = CDLL('libc.so.6')

class uts_struct(Structure):
    _fields_ = [ ('sysname', c_char_p),
                 ('nodename', c_char_p),
                 ('release', c_char_p),
                 ('version', c_char_p),
                 ('machine', c_char_p) ]

utsname = uts_struct()
libc.uname(byref(utsname))

print utsname.sysname

これは同じことをします:

from ctypes import *

libc = CDLL('libc.so.6')

class uts_struct(Structure):
    _fields_ = [ ('sysname', c_char_p),
                 ('nodename', c_char_p),
                 ('release', c_char_p),
                 ('version', c_char_p),
                 ('machine', c_char_p) ]

utsname = uts_struct()
utsname_pointer = pointer(utsname)
libc.uname(utsname_pointer)

print utsname.sysname

私は何か基本的なことを台無しにしているに違いありません...

(私は知っていos.uname()ます、これは私が失敗している理解の練習にすぎません)

ここでunameマニュアルを参照しました:http ://www.cl.cam.ac.uk/cgi-bin/manpage?2 + uname

私は何が間違っているのですか?


編集:

Nemoのおかげで、データを取得できました。

>>> from ctypes import *
>>> libc = CDLL('libc.so.6')
>>> gnar = create_string_buffer(512)
>>> libc.uname(byref(gnar))
0
>>> print gnar.value
Linux
>>> 

ただし、レギュレーター文字列と同様に、項目がNULLで区切られているため、「Linux」のみを取得していると想定しています。NULLを超えて読み取る方法はありますか?


Edit2:

Nemosのコメントに基づいて、私はこれを試しました-これは機能しませんが、正しい方向への一歩かもしれないと思いました...エラー:

Traceback (most recent call last):
  File "gnar.py", line 18, in <module>
    utsname = uts_struct(gnar)
TypeError: incompatible types, c_char_Array_512 instance instead of c_char_p instance

これは実行不可能ですか?

from ctypes import *

libc = CDLL('libc.so.6')

class uts_struct(Structure):
    _fields_ = [ ('sysname', c_char_p),
                 ('nodename', c_char_p),
                 ('release', c_char_p),
                 ('version', c_char_p),
                 ('machine', c_char_p) ]

gnar = create_string_buffer(512)
libc.uname(byref(gnar))
utsname = uts_struct(gnar)

Edit3:(これまでで最も長い投稿を目指しています...=P)

from ctypes import *
libc = CDLL('libc.so.6')
class uts_struct(Structure):
    _fields_ = [ ('sysname', c_char * 65),
                 ('nodename', c_char * 65),
                 ('release', c_char * 65),
                 ('version', c_char * 65),
                 ('machine', c_char * 65) ]
gnar = uts_struct()
libc.uname(byref(gnar))
print gnar.machine

これは機能しますが、値を出力した後にセグフォールトします...


最終編集:

次の作品-私はもちろんGNUバージョンのlibcを使用しています。(Ubuntuマシンのim)したがって、ドメインのフィールドを追加するだけで、セグメンテーション違反を停止できます。後から考えると理にかなっています。:)

from ctypes import *

libc = CDLL('libc.so.6')

class uts_struct(Structure):
    _fields_ = [ ('sysname', c_char * 65),
                 ('nodename', c_char * 65),
                 ('release', c_char * 65),
                 ('version', c_char * 65),
                 ('machine', c_char * 65),
                 ('domain', c_char * 65) ]

gnar = uts_struct()
libc.uname(byref(gnar))
print gnar.nodename
4

2 に答える 2

2

utsname構造体のフィールドはポインターではありません。それらは「不特定のサイズの配列」です。

したがって、文字列は構造内で連続してパックされ、nullで終了します。

Pythonでこれを表現する方法がわかりません。ただし、実験にはuname()以外のものから始めることをお勧めします。:-)

[アップデート]

517366245708の10進数は0x78756E694Cで、これは「xuniL」のASCIIです。これは、64ビットのリトルエンディアンマシンでは実際に意味があります...

ただし、問題は、c_char_pを使用してポインターを作成し、byref()を呼び出すときにそのポインターを渡すことです。したがって、uname()はポインタを埋めています(それが指しているものではありません)。さらに悪いことに、そこには8バイトを超えるバイトが含まれているため、現在のコードはメモリを破壊しています。

メモリのブロックをaのサイズで割り当てる方法を理解し、それstruct utsnameへのポインタをuname()関数に渡して、そのブロック内のどのオフセットが構造体のどのフィールドに対応するかを理解する必要があります。Pythonでこれがどれだけ可能かはわかりません...

【2回目の更新】

それは良いことです...しかし今、あなたは配列内のオフセットを見る必要があります。これが典型的なLinuxシステムの場合、各フィールドは65バイトです(はい、実際に)。したがって、文字列への65バイトの読み取りを開始する必要があります。あなたがこのことを呼びかけることができるかどうかはわかりませんstring.index...

于 2011-06-02T22:19:35.307 に答える
2

このunameのマニュアルページによると、構造体には、char *(c_char_p)ではなく、実装で定義されたサイズの配列が含まれています。の構造定義を見たことがありますsys/utsname.hか?構造の定義を正確に一致させる必要があります。データ型はおそらく次のようになりますc_char * n。ここで、nはで見つかったそのフィールドの配列のサイズですsys/utsname.h

または、バッファが構造全体に対して十分な大きさである限り、を使用して最初の編集ですべての文字列にアクセスできる必要があります。print gnar.raw

于 2011-06-03T00:41:39.913 に答える