2017-02-28 12 views
5

にPythonの辞書の変換:私は次のエントリでPythonの辞書を持っているctypesの構造

struct CA { 
    char *Keys; 
    float *Values; 
    char *Title; 
    int Index; 
}; 

void myfunc (struct CA *in, int n); 

Tmp={'Name1': [10.0, 20.0, 'Title1', 1], 'Name2': [5.0, 25.0, 'Title2', 2]} 

私は、関数は次のように定義されたC-関数にこれを渡したいですPython側では、

class CA(ctypes.Structure): 
    _fields_ = [("Keys", ctypes.POINTER(ctypes.c_char_p)), 
       ("Values", ctypes.POINTER(ctypes.c_float)), 
       ("Title", ctypes.POINTER(ctypes.c_char_p)), 
       ("Index", ctypes.c_int)] 

のようなctypes構造を作成し、次のコードを使用してCAの配列を作成しました。

CAarray = CA * 2 

は、今私は

k = Tmp.keys() 
for (j, _) in enumerate(k): 
    CAarray[j].Keys = _ 
    CAarray[j].Values = Tmp[_][:2] 
    CAarray[j].Title = Tmp[_][2] 
    CAarray[j].Index = Tmp[_][3] 

そのようなループにCAarrayへのTmpを割り当てたい私は、構文が正しい取得するために苦労してきた、これまで失敗しています。助けて。

Python変数とctypes変数間の変換を処理できるルーチン/ libはありますか?

答えて

0

この程度正確にわからないが、動作するようです:

tmp = {'Name1': [10.0, 20.0, 'Title1', 1], 'Name2': [5.0, 25.0, 'Title2', 2]} 

class CA(ctypes.Structure): 
    _fields_ = [("key", ctypes.POINTER(ctypes.c_wchar_p)), 
      ("values", ctypes.POINTER(ctypes.c_float)), 
      ("title", ctypes.POINTER(ctypes.c_wchar_p)), 
      ("index", ctypes.c_int)] 

CAArray = CA * 2 
ca_array = CAArray() 

for ca, key in zip(ca_array, tmp): 
    ca.key = ctypes.pointer(ctypes.c_wchar_p(key)) 
    ca.values = ctypes.pointer(ctypes.c_float(tmp[key][0])) 
    ca.title = ctypes.pointer(ctypes.c_wchar_p(tmp[key][2])) 
    ca.index = tmp[key][3] 

for ca in ca_array: 
    print(ca.key[0], ca.values[0], ca.values[1], ca.title[0], ca.index) 

私も命名規則のPythonに貼り。

+0

rolika申し訳ありませんが、それは動作しません。 ca_arrayがC関数myfuncに渡されると(クエリを参照)、私はすべての値を取得します。 myfuncの最初の引数は構造体CAの配列です。 – Rak

3

構造が正しく渡ることを確認するためのテストDLLを作成しました。ここで

#include <stdio.h> 

struct CA { 
    char *Keys; 
    float *Values; 
    char *Title; 
    int Index; 
}; 

__declspec(dllexport) void myfunc (struct CA *in, int n) 
{ 
    int i; 
    for(i = 0; i < n; ++i) 
    { 
     printf("%d: Keys = %s\n",i,in[i].Keys); 
     printf("%d: Values = %f %f\n",i,in[i].Values[0],in[i].Values[1]); 
     printf("%d: Title = %s\n",i,in[i].Title); 
     printf("%d: Index = %d\n",i,in[i].Index); 
    } 
} 

は、私はそれを呼ばれる方法は次のとおりです。

#!python3 
from ctypes import * 

class CA(Structure): 
    _fields_ = [('Keys',c_char_p), 
       ('Values',POINTER(c_float)), 
       ('Title',c_char_p), 
       ('Index',c_int)] 

Tmp={'Name1': [10.0, 20.0, 'Title1', 1], 'Name2': [5.0, 25.0, 'Title2', 2]} 

# repackage Tmp as a list of CA structures 
ca_list = [] 
for k,v in Tmp.items(): 
    ca = CA() 
    ca.Keys = k.encode('utf8') # Python 3 strings are Unicode, char* needs a byte string 
    ca.Values = (c_float*2)(v[0],v[1]) # Interface unclear, how would target function know how many floats? 
    ca.Title = v[2].encode('utf8') 
    ca.Index = v[3] 
    ca_list.append(ca) 

# repackage python list of CAs to ctype array of CAs 
ca_array = (CA * len(ca_list))(*ca_list) 

dll = CDLL('test') 
dll.myfunc.argtypes = POINTER(CA),c_int 
dll.myfunc.restype = None 

dll.myfunc(ca_array,len(ca_array)) 

は出力:

0: Keys = Name1 
0: Values = 10.000000 20.000000 
0: Title = Title1 
0: Index = 1 
1: Keys = Name2 
1: Values = 5.000000 25.000000 
1: Title = Title2 
1: Index = 2 
+0

素晴らしい!ありがとう、それは動作します。重要な部分は文字列を 'utf8'でエンコードすることです。私は、最初の文字だけを受け取った文字列を除き、すべての値がC関数によって正しく捕捉されたところまで、Rolikaの解を修正することができました。あなたのソリューションは、最後のビットを解決するのに役立ちました... – Rak

関連する問題