【发布时间】:2014-08-29 21:42:09
【问题描述】:
所以到目前为止我所做的是构建一个小的 ctypes 和 python 代码,它执行以下操作:
Python 以指向 void 指针的指针作为参数调用 C 函数。
C 代码创建一个
ReturnStruct类型的结构并实例化它及其数据成员,然后将python 传入的指针设置为指向该结构。Python 多次调用另一个 C 函数来增加某些值。
Python 然后检查这些值。
Python 调用一个 C 函数来释放结构指针。
到目前为止,我已经完成了前 3 个阶段,但我在后两个部分遇到了问题。这是C代码:
#include <stdio.h>
#include <stdlib.h>
//#include "runSolver.h"
#define SMB_MAX_DATA_SIZE 16
typedef struct testStruct {
double *x[11];
double *u[10];
} Test;
typedef struct returnStruct_t {
Test* vars;
} ReturnStruct;
void initalize_returnStruct(void** returnStruct){
ReturnStruct* new_returnStruct = (ReturnStruct *)malloc(sizeof(ReturnStruct));
Test* varsStruct = (Test*)malloc(sizeof(Test)*3);
int dataSize = 5;
int i;
for(i = 0; i < 3; i++){
int x;
for(x = 0; x < 11; x++)
varsStruct[i].x[x] = (double *)malloc(sizeof(double)*5);
for(x = 0; x < 10; x++)
varsStruct[i].u[x] = (double *)malloc(sizeof(double)*5);
}
new_returnStruct->vars = varsStruct;
*returnStruct = new_returnStruct;
}
void free_returnStruct(void* data){
ReturnStruct* returnStruct = data;
int i;
for(i = 0; i < 3; i++){
int x;
for(x = 1; x < 11; x++)
free(returnStruct->vars[i].x[x]);
for(x = 0; x < 10; x++)
free(returnStruct->vars[i].u[x]);
}
free(returnStruct->vars);
free(returnStruct);
}
void parallelSolver(void* data){
ReturnStruct* VarsArray = data;
fprintf(stderr, " This is the value: %f \n", VarsArray->vars[0].x[0][0]);
fprintf(stderr, " This is the value: %f \n", VarsArray->vars[0].x[10][4]);
fprintf(stderr, " This is the value: %f \n", VarsArray->vars[0].u[0][0]);
fprintf(stderr, " This is the value: %f \n", VarsArray->vars[0].u[9][2]);
VarsArray->vars[0].x[0][0] += 20.0;
VarsArray->vars[0].x[10][4] += 203.0;
VarsArray->vars[0].u[0][0] += 202.0;
VarsArray->vars[0].u[9][2] += 202.0;
}
这里是python代码:
#!/usr/bin/python
import sys
import ctypes as ct
numOpt = 3
class vars_t(ct.Structure):
_fields_ = [("u", ct.POINTER(ct.c_double*10)),
("x", ct.POINTER(ct.c_double*11))]
class returnStruct_t(ct.Structure):
_fields_ = [("vars", vars_t*numOpt)]
runSolver = ct.CDLL('./runSolverParallel.so')
returnStructPointer = ct.POINTER(returnStruct_t)
runSolver.parallelSolver.argtypes = [ct.c_void_p()]
varsd = ct.c_void_p()
runSolver.initalize_returnStruct(ct.byref(varsd))
runSolver.parallelSolver(varsd)
runSolver.parallelSolver(varsd)
runSolver.parallelSolver(varsd)
runSolver.parallelSolver(varsd)
varsdb = ct.cast(varsd, returnStruct_t)
print(varsdb.contents.vars[0].x[0][0])
runSolver.free_returnStruct(varsd)
代码运行良好,直到我到达这三行:
varsdb = ct.cast(varsd, returnStruct_t)
print(varsdb.contents.vars[0].x[0][0])
runSolver.free_returnStruct(varsd)
所有这些都会产生段错误。任何有关如何使其正常工作的建议将不胜感激!
错误如下所示:
Starting program: /usr/bin/python UserDefinedCode.py
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
This is the value: 0.000000
This is the value: 0.000000
This is the value: 0.000000
This is the value: 0.000000
This is the value: 20.000000
This is the value: 203.000000
This is the value: 202.000000
This is the value: 202.000000
This is the value: 40.000000
This is the value: 406.000000
This is the value: 404.000000
This is the value: 404.000000
This is the value: 60.000000
This is the value: 609.000000
This is the value: 606.000000
This is the value: 606.000000
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff33795d4 in ?? () from /usr/lib/python2.7/lib-dynload/_ctypes.so
(gdb) where
#0 0x00007ffff33795d4 in ?? () from /usr/lib/python2.7/lib-dynload/_ctypes.so
#1 0x00007ffff3386ea4 in ffi_call_unix64 () from /usr/lib/python2.7/lib-dynload/_ctypes.so
#2 0x00007ffff33868c5 in ffi_call () from /usr/lib/python2.7/lib-dynload/_ctypes.so
#3 0x00007ffff33772c2 in _ctypes_callproc () from /usr/lib/python2.7/lib-dynload/_ctypes.so
#4 0x00007ffff3377aa2 in ?? () from /usr/lib/python2.7/lib-dynload/_ctypes.so
#5 0x00000000004d91b6 in PyObject_Call ()
#6 0x000000000054c0da in PyEval_EvalFrameEx ()
#7 0x000000000054c272 in PyEval_EvalFrameEx ()
#8 0x0000000000575d92 in PyEval_EvalCodeEx ()
#9 0x00000000004c1352 in PyRun_SimpleFileExFlags ()
#10 0x00000000004c754f in Py_Main ()
#11 0x00007ffff68cb76d in __libc_start_main (main=0x41ba10 <main>, argc=2, ubp_av=0x7fffffffe1d8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe1c8)
at libc-start.c:226
#12 0x000000000041ba41 in _start ()
【问题讨论】:
-
你能把它分解成一个更小的MCVE,它不会做一堆不相关的事情,不需要
scipy等吗?这将使调试变得更加容易。 -
另外,当我运行它时,我得到的每个其他数字都类似于
26815615859885194199148049996411692254958731641184786755447122887443528060147093953603748596333806855380063716372972101707507765623893139892867298012168192.000000。你确定 C 代码是正确的吗? -
我也注意到了这一点,但如果我在这两种情况下都将
x[10][4]更改为x[10][3],它又开始工作了。不知道那里发生了什么。 -
ct.cast(varsd, returnStruct_t)几乎肯定会出现段错误。这就像在做returnStruct_t = *(returnStruct_t *)(&varsd)。你可能想要ct.cast(varsd, returnStructPointer)? -
好吧,如果您的 C 代码不正确并且可能打印出未初始化的内存或其他内容,那么从
ctypessegfaults 调用它也就不足为奇了。您是否尝试过从普通的旧 C 驱动程序调用相同的东西?