2012-07-06 2 views
8

私のライブラリのLinuxポートにリンクするために、Windows固有のプログラムからPython​​コードを移植しようとしています。私の問題を記述する最短のPythonコードサンプルを以下に示します。私がそれを実行しようとすると、私はPythonのexamine_arguments()にセグメンテーション違反を受け取ります。私はprintfステートメントをクラッシュ関数呼び出し時にライブラリに配置しましたが、決して実行されないので、問題がctypesコードにあると思うようになります。Pythonのctypesセグメンテーションフォールトのデバッグ

import ctypes 

avidll = ctypes.CDLL("libavxsynth.so") 


class AVS_Value(ctypes.Structure, object): 
    def __init__(self, val=None): 
     self.type=ctypes.c_short(105) # 'i' 
     self.array_size = 5 
     self.d.i = 99 


class U(ctypes.Union): 
    _fields_ = [("c", ctypes.c_void_p), 
       ("b", ctypes.c_long), 
       ("i", ctypes.c_int), 
       ("f", ctypes.c_float), 
       ("s", ctypes.c_char_p), 
       ("a", ctypes.POINTER(AVS_Value))] 


AVS_Value._fields_ = [("type", ctypes.c_short), 
         ("array_size", ctypes.c_short), 
         ("d", U)] 


avs_create_script_environment = avidll.avs_create_script_environment 
avs_create_script_environment.restype = ctypes.c_void_p 
avs_create_script_environment.argtypes = [ctypes.c_int] 

avs_set_var = avidll.avs_set_var 
avs_set_var.restype = ctypes.c_int 
avs_set_var.argtypes = [ctypes.c_void_p, ctypes.c_char_p, AVS_Value] 


env = avs_create_script_environment(2) 
val = AVS_Value() 
res = avs_set_var(env, b'test', val) 

マイライブラリには、そのヘッダに以下を持ち、かつ(set_var続いcreate_script_environmentを呼び出す)私は上記の説明何をしてプレーンな-Cプログラムが正常に動作。私の図書館がコンソールに置いているログ情報を見ると、avs_set_varと入力するとクラッシュします。

typedef struct AVS_ScriptEnvironment AVS_ScriptEnvironment; 
typedef struct AVS_Value AVS_Value; 
struct AVS_Value { 
    short type; // 'a'rray, 'c'lip, 'b'ool, 'i'nt, 'f'loat, 's'tring, 'v'oid, or 'l'ong 
       // for some function e'rror 
    short array_size; 
    union { 
    void * clip; // do not use directly, use avs_take_clip 
    char boolean; 
    int integer; 
    float floating_pt; 
    const char * string; 
    const AVS_Value * array; 
    } d; 
}; 
AVS_ScriptEnvironment * avs_create_script_environment(int version); 
int avs_set_var(AVS_ScriptEnvironment *, const char* name, AVS_Value val); 

私は、GDBから呼び出しをバックトレースしようとしたが、私は結果を解釈する方法を理解したり、GDBを使用してについて本当に多くありません。

#0 0x00007ffff61d6490 in examine_argument() from /usr/lib/python2.7/lib-dynload/_ctypes.so 
#1 0x00007ffff61d65ba in ffi_prep_cif_machdep() from /usr/lib/python2.7/lib-dynload/_ctypes.so 
#2 0x00007ffff61d3447 in ffi_prep_cif() from /usr/lib/python2.7/lib-dynload/_ctypes.so 
#3 0x00007ffff61c7275 in _ctypes_callproc() from /usr/lib/python2.7/lib-dynload/_ctypes.so 
#4 0x00007ffff61c7aa2 in PyCFuncPtr_call.2798() from /usr/lib/python2.7/lib-dynload/_ctypes.so 
#5 0x00000000004c7c76 in PyObject_Call() 
#6 0x000000000042aa4a in PyEval_EvalFrameEx() 
#7 0x00000000004317f2 in PyEval_EvalCodeEx() 
#8 0x000000000054b171 in PyRun_FileExFlags() 
#9 0x000000000054b7d8 in PyRun_SimpleFileExFlags() 
#10 0x000000000054c5d6 in Py_Main() 
#11 0x00007ffff68e576d in __libc_start_main() from /lib/x86_64-linux-gnu/libc.so.6 
#12 0x000000000041b931 in _start() 

私はこの問題にどのように近づいていますか。私は呼び出し型の詳細を見てきましたが、明らかに間違っているものはありません。プラットフォーム固有の型に陥っていますか?

を編集します。ctypesモジュールの32ビットと64ビットのアーキテクチャに問題があるようです。これを私のライブラリと32ビットPythonの32ビットビルドで再度テストしたところ、正常に実行されました。 64ビットでは、同じ場所でセグメンテーションが行われます。

+0

私は、このコードをコピー明らか誤貼り付けビットを並び替え、2つの関数のいくつかのダミー実装した、コンパイルそれはx86_64用で、64ビットPython 2.7(Ubuntu Natty、gcc 4.5.2、Python 2.7.1、eglibc 2.13)で動作し、すべてが期待どおりに動作しました。ここでctypesの問題を非難するのは早すぎるようです。おそらくより完全な例を提供することができますか? –

+0

コード例をクリーンアップしました。 segfaultは、AVS_Valueクラスの一部であるユニオンに関連しているようです。私がctypes.c_intやctypes.c_void_pのようなものに置き換えると、プログラムはもはやsegfaultsになりません。私は問題がUbuntuにインストールされたPythonであると思っています。Ubuntu 12.04、GCC 4.6.3、Python 2.7を使用しています。 – user1505563

答えて

0

は不透明AVS_ScriptEnvironment*ためc_void_pを使用してみてください:

​​

と:

avs_set_var.argtypes=[c_void_p,ctypes.c_char_p,AVS_Value] 
+0

戻り値の型をc_void_pに明示的に設定しても問題ありません。私は次の関数を入力する前にPythonがクラッシュするので、なぜそのようになるのか分かりません。そのため、ポインタは何も行われません。 – user1505563