作者KSJ (阿真)
看板Python
标题Re: [问题] 让Python 用C运算 之 传变数的问题
时间Sun Jun 7 00:11:49 2009
※ 引述《sbrhsieh (sbr)》之铭言:
: ※ 引述《KSJ (阿真)》之铭言:
: : 但是 我认为这个"长的程式" 应该也可以在C中使用吧??(这部份想请教)
: : 也就是说:
: : 在C写一个py函式
: : static PyObject *funcA (PyObject *self, PyObject *args)
: : {
: : (把args做一些修改变成args2)//一段程式码
: /* 在这里插入对 standard output 输出一些讯息的码 */
: : PyObject *value = funcB(NULL,args2); //另一个写好的funcB
: : return Py_BuildValue("N",value);
: : }
: : 不知道这样行不行得通
: : 里面的funcB就是我的"长的程式"
: : 单单使用funcB是没问题的
: : 而要使用funcA传变数给funcB使用 就会有"误"
: : "误"是指 程式爆掉 不是例外 是XP不回报的那种
: 感觉上很有可能在你没有揭露的"把args做一些修改变成args2"这一段码就错了,
: 搞到程式死掉。先弄清楚到底是死在哪一部份。
首先想先确认 因为没有怀疑"所写的函式 可以被呼叫"这件事
那这样的动作应该是可行了(我也希望是这样)
我来仔细说明我的做法 首先
python的函式 只包含2个变数要传入 一个是self,另一个是args
self我读到认为是只用在method 用function时self是一个指向NULL的指标
args则想成是所有需要的变数包装 我常用一个list或tuple把需要的变数放在里面
所以说 funcA 与 funcB 他们接受的变数 可以想成同一类 list or tuple
传入後 再去考虑要怎麽接list里的一个个变数
我的funcB 我是用以下的方式去接的(变数当成已宣告):
if (!PyArg_ParseTuple(args, "(OOOOI)", \
&pylagS,&pylagT,&pyCOV,&pyFitVar,&func_num)) return NULL;
事实上我传进去的是一个长得像这样
([1,1,2,2],[1,2,1,2],[5,4,6,3],(4,3),0) 的一个tuple
在只使用funcB (也就是以上是在python的idle用手打的)时 是可以跑完的
所以我认定 只要在c中 创造出这样一个tuple 传进funcB中 应该也是可行
创造tuple的工作 就必须在funcA中完成 也就是先前所提的 把args转为args2
//我必须先把funcA的变数转成List 才能使用内建的insert()方法
PyObject *pyFUNC_VARIABLEseqList = PySequence_List(pyFUNC_VARIABLEseq)
//经过转换 输进funcA的args应该长
//[[1,1,2,2],[1,2,1,2],[5,4,6,3], 0]
//本来的[4,3] 必须由funcA中新开的变数来做设定
//开一个tuple ( 也就是(4,3) 只是里面的数字会变) 准备让args insert 它
PyObject *pyVarTuple = PyTuple_New(Nseqlength);
//放变数 想成 Nseqlength 是2就好 (测试也是用2 虽然我是写n的)
for (j=0;j<Nseqlength;j++)
{
//index的转换 好像32位元的没差 但64的会有 我就先转了
PyObject *pyj = PyInt_FromLong(j);
Py_ssize_t pyj_index = PyInt_AsSsize_t(pyj);
Py_DECREF(pyj);
PyTuple_SET_ITEM \
(pyVarTuple, pyj_index, PyFloat_FromDouble(Location[i*Nseqlength+j]));
}
Py_ssize_t index = 3; //insert的位置 这个可以确定是3
//也就是(4,3)的位置
//做insert的动作
PyList_Insert(pyFUNC_VARIABLEseqList,index,pyVarTuple);
//将insert後的list (也就是args2) 转成tuple
//主要是运用会产生new reference的特性 产生所谓真正的args2
PyObject *pyFUNC_VARIABLEseqTuple =\
PySequence_Tuple(pyFUNC_VARIABLEseqList);
//要的东西(args2)有了 剩的(args、插入用的tuple)就DECREF掉
Py_DECREF(pyFUNC_VARIABLEseqList);
Py_DECREF(pyVarTuple);
//下面这行本来是看看传进下面funcB之前 这东西倒底有没有问题的
//return Py_BuildValue("N",pyFUNC_VARIABLEseqTuple);
//结果是
//([1, 1, 2, 2], [1, 2, 1, 2], [5, 4, 6, 3], (8.72, 5.52), 0)
//所以我认定应该是没问题 才继续下面这一行
PyObject *value = (*func)(NULL,pyFUNC_VARIABLEseqTuple);
於是在这里的最後一行 程式有误
想必是进入funcB之後的问题?!
於是我在funcB之中加入一些中断点 来看看是哪里的问题
funcB只秀到有误的部份:
//宣告要接的变数 有一个长整数 四个pyobejct
//长整数就是 最後的那个 0 四个pyobject就是
//[1,1,2,2,] [1,2,1,2] [5,4,6,3] (8.72,5.52) 这四个
long int func_num;
PyObject *pylagS,*pylagT,*pyCOV,*pyFitVar;
PySys_WriteStdout("parse OK");//中断点1
//传递参数
if (!PyArg_ParseTuple(args, "(OOOOI)",\
&pylagS,&pylagT,&pyCOV,&pyFitVar,&func_num)) return NULL;
PySys_WriteStdout("parse OK");//中断点2
到中断点1 印出parse OK 之後
程式就爆了…orz
强调一下 如果单单只叫funcB (用手key值) 是没问题的
但由funcA 叫funcB 就爆了(如上…)
传变数看起来也ok… 所以…请大家帮个忙 囧
感激不尽 <(_ _)>
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 140.112.63.180
※ 编辑: KSJ 来自: 140.112.63.180 (06/07 00:22)
1F:推 Tiberius:看不懂 ... 整颗包起来给个下载连结, 我有看到再 de 看看 06/07 16:55
3F:→ KSJ:里面用到的是 WMSE 跟 PSO PSO呼叫WMSE时有误 06/08 14:10