0

私はpythonとctypesの初心者です。私が持っているものは:-

C プログラム:

struct query
{
  uint16_t req_no;
  uint32_t req_len;
  uint64_t req;
};

struct response
{
  uint16_t req_no;
  uint16_t status;
  uint32_t value_len;
  uint64_t value;
};

// functions for creating query and response packets using
// above structs respectively, returning char buffer.
char* create_query(//some args);
char* create_response(//some args);

上記の C コードの libquery.so を作成しました。私の TCP サーバーは C プログラムです。同じためにTCP pythonクライアントを作成しようとしています(私のプロジェクトにはそれが必要です!)。

Pythonクライアントから(libquery.soの関数を使用して)クエリを正常に送信し、データを受信できます。しかし、応答データを取得したら、それを「構造体応答」型に変換したいと考えています。Pythonで同様の「構造」クラスを作成しましたが、何も得られません。

助けてください。

私のPythonコードのいくつかのコードスニペット:-

// some ctypes imports 
lib = cdll.LoadLibrary('./libquery.so')

class Info1(Structure):
    _fields_ = [("req_no",c_int),
                ("status",c_int),
                ("value_len",c_int),
                ("value",c_int)]

header = Info1()

// Did some TCP connection code here and send data to server by calling
// create_query() method, data confirmed to be correct on server side...

# Receive response data
data = sock.recv(512)
header = str_to_class('Info1')

header.req_no    =  int(ord(data[0])) // Works; but I don't want to go this ways..
header.status    =  int(ord(data[1]))
header.value_len =  int(ord(data[2]))
header.value     =  int(ord(data[3]))

print above header values..

私は使用してみました:-

 def str_to_class(Info1):
    return getattr(sys.modules[__name__], Info1)

しかし、それを機能させる方法がわかりません。

誰かがそれを機能させる方法を知っていますか、それとも他の方法はありますか??

4

1 に答える 1

2

あなたの 'Info1' は C の 'struct response' と一致しません。そこで、次のコードに変更しました。ctypes.memmoveを使用できます。

from ctypes import *

class Info1(Structure):
    _fields_ = [("req_no", c_uint16),
                ("status", c_uint16),
                ("value_len", c_uint32),
                ("value", c_uint64)]

data = (
    '\x01\x00'
    '\x02\x00'
    '\x03\x00\x00\x00'
    '\x04\x00\x00\x00\x00\x00\x00\x00'
)
# Assumed data was received. I assumed both server, clients are little-endian.
# else, use socket.ntoh{s|l}, socket.hton{s|l} ....

header = Info1()
memmove(addressof(header), data, sizeof(header))
assert header.req_no == 1
assert header.status == 2
assert header.value_len == 3
assert header.value == 4

structも使用できます。

import struct
data = '....' # same as above
struct.unpack('HHLQ', data) == (1, 2, 3, 4) # '>HHLQ' if data is htonl/htons-ed in sencding part.
于 2013-06-15T07:35:46.523 に答える