1

私は現在、C で Python 拡張機能を作成する方法を学ぼうとしていますが、すべてうまくいっているようです。ただし、比較関数を使用しようとすると、すべてセグメンテーション違反が発生します。例えば:

#include "Python.h"

int test(void) {
    int result;
    printf("Before compare...\n");
    result = PyObject_Compare(PyInt_FromLong(1), PyInt_FromLong(3));
    printf("result= %d\n", result);
    return 0;   
}

Python から実行するtest()と (私は ctypes を使用しました)、次の出力が得られます。

Before compare...
Segmentation fault

これは、次のような他の比較関数で私に起こりました: PyObject_cmp...など

どんな助けでも大歓迎です、ありがとう。

より詳しい情報:

最初にファイル (test.c) を共有ライブラリにコンパイルしました。

$> python-config --cflags
-I/usr/include/python2.7 -I/usr/include/python2.7 -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes
$> python-config --ldflags
-L/usr/lib/python2.7/config -lpthread -ldl -lutil -lm -lpython2.7 -Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions

$> gcc -c $(python-config --cflags) ./test.c -o test.o
$> gcc -shared  ./test.o  $(python-config --ldflags) -o libtest.so

次に、次のように Python から関数を開始しました。

import ctypes
testlib = ctypes.CDLL('./libtest.so')

testlib.test()

編集:

Viktor によって与えられたテストの使用

$> gcc -o dlltest test.c -ldl
$> gdb dlltest
(gdb) run
Starting program: dlltest 
[Thread debugging using libthread_db enabled]
Cannot find new threads: generic error
(gdb) 

だから私はこれをしました:

$> LD_PRELOAD=libpthread-2.13.so gdb dlltest
(gdb) run
Starting program: dlltest
[Thread debugging using libthread_db enabled]
Before compare...
result= -1
[Inferior 1 (process 3274) exited normally]
(gdb)

編集2:

>$ gdb --args python frompython.py
(gdb) run
Starting program: /usr/bin/python frompython.py
[Thread debugging using libthread_db enabled]
Before compare...

Program received signal SIGSEGV, Segmentation fault.
0x080a855b in PyObject_Compare ()
(gdb) backtrace
#0  0x080a855b in PyObject_Compare ()
#1  0x005225d8 in test () at ./testmod.c:29
#2  0x005181ca in ffi_call_SYSV ()
   from /usr/lib/python2.7/lib-dynload/_ctypes.so
#3  0x00517eff in ffi_call () from /usr/lib/python2.7/lib-dynload/_ctypes.so
#4  0x00510312 in _ctypes_callproc ()
   from /usr/lib/python2.7/lib-dynload/_ctypes.so
#5  0x0050788d in ?? () from /usr/lib/python2.7/lib-dynload/_ctypes.so
#6  0x0805dc31 in PyObject_Call ()
#7  0x080f81c1 in PyEval_EvalFrameEx ()
#8  0x080fd804 in PyEval_EvalCodeEx ()
#9  0x080fe177 in PyEval_EvalCode ()
#10 0x0811acd0 in ?? ()
#11 0x0811b8e9 in PyRun_FileExFlags ()
#12 0x0811c4cc in PyRun_SimpleFileExFlags ()
#13 0x0812c7c6 in Py_Main ()
#14 0x0805da0b in main ()
(gdb) 
4

1 に答える 1

5

'test()' 関数には Python のインタープリターの初期化はありません (Py_Initialize 呼び出しはありません)。

PyInt_FromLong() は内部配列へのポインターを返しますが、これはあなたのケースでは初期化されていません。したがって、無効なポインターを取得し、それを Py_Compare() 関数に渡すと、インタープリターがクラッシュします。

初期化の詳細については、こちらを参照してください: http://docs.python.org/c-api/init.html#initializing-and-finalizing-the-interpreter

少なくとも、test() 関数の先頭に "Py_Initialize()" 呼び出しを追加してみてください。

編集:

興味深いことに、このプログラムを使用して C から libtest.test を実行すると、GDB からのスタック トレースはどうなるでしょうか。

#include <dlfcn.h>

typedef int (*fcn)();

int main()
{
    void* dll = dlopen("libtest.so", RTLD_LAZY);

    /* dlerror checks here */

    fcn Test = (fcn)dlsym(dll, "test");

    Test();

    dclose(dll);

    return 0;
}

EDIT2:

  1. テストをコンパイルします (gcc -o dlltest test.c -ldl)

  2. 「gdb dlltest」を実行します

  3. gdbプロンプトでコマンド「run」を入力します

  4. クラッシュするかどうかを確認する

  5. はいの場合は、gdb のプロンプトにバックトレースを入力します。

EDIT3:

墜落の場所は明らかではありません。「fflush(stdout);」を追加してみてください。各 printf() 呼び出しの後、エラーが確実に出力されるようにします。

Python ベースのアプリに "result= -1" が表示される場合、エラーは libtest.so ではなく ctypes にあります。

于 2012-06-04T07:40:46.707 に答える