我想通过使用ctypes在一些Python代码中使用C库。 我的问题是我不懂C语言。我试着读代码和C结构已经好几天了,但我还是被一个问题困住了。我对Python也相当陌生,因为我目前正在从Matlab进行转换,因此我的Python仅限于科学的Python应用程序。这个问题非常具体,但我认为解决方案是一般C库/Python链接感兴趣的。在
我用的是一个叫做Iphreeqc的地球化学模型`http://wwwbrr.cr.usgs.gov/projects/GWC_coupled/phreeqc/index.html(iphreeqc-2.18.0-5314。焦油gz,从OS X 10.6上的源代码编译。超链接不工作,因为SO垃圾邮件预防)。我想从C库的计算中提取值到Python中。在
我怀疑我在Python代码的结构和联合部分中出错了,但我似乎无法找出原因。在
Python代码:
import ctypes
iphreeqc = ctypes.CDLL("libiphreeqc.0.dylib", ctypes.RTLD_GLOBAL)
# C structures from var.h
class VAR_TYPE(ctypes.Structure):
_fields_ = [
("TT_EMPTY",ctypes.c_int),
("TT_ERROR",ctypes.c_int),
("TT_LONG",ctypes.c_int),
("TT_DOUBLE",ctypes.c_int),
("TT_STRING",ctypes.c_int)]
(TT_EMPTY,
TT_ERROR,
TT_LONG,
TT_DOUBLE,
TT_STRING)=map(ctypes.c_int, xrange(5))
class VRESULT(ctypes.Structure):
_fields_ = [
("VR_OK",ctypes.c_int),
("VR_OUTOFMEMORY",ctypes.c_int),
("VR_BADVARTYPE",ctypes.c_int),
("VR_INVALIDARG",ctypes.c_int),
("VR_INVALIDROW",ctypes.c_int),
("VR_INVALIDCOL",ctypes.c_int)]
(VR_OK,
VR_OUTOFMEMORY,
VR_BADVARTYPE,
VR_INVALIDARG,
VR_INVALIDROW,
VR_INVALIDCOL)=map(ctypes.c_int, xrange(0,-6,-1))
class _U(ctypes.Union):
_fields_ = [("lVal", ctypes.c_long),
("dVal", ctypes.c_double),
("sVal", ctypes.c_char),
("vresult", VRESULT)]
class VAR(ctypes.Structure):
_anonymous_ = ("pvar",)
_fields_ = [
("pvar", _U),
("type", VAR_TYPE)]
# Run model
Id=iphreeqc.CreateIPhreeqc()
dbloade = iphreeqc.LoadDatabase(Id,"phreeqc.dat")
estring=iphreeqc.OutputErrorString(Id)
# Model input
iphreeqc.AccumulateLine(Id,"TITLE Example 2.--Temperature dependence of solubility")
iphreeqc.AccumulateLine(Id," of gypsum and anhydrite ")
iphreeqc.AccumulateLine(Id,"SOLUTION 1 Pure water ")
iphreeqc.AccumulateLine(Id," pH 7.0 ")
iphreeqc.AccumulateLine(Id," temp 25.0 ")
iphreeqc.AccumulateLine(Id,"EQUILIBRIUM_PHASES 1 ")
iphreeqc.AccumulateLine(Id," Gypsum 0.0 1.0 ")
iphreeqc.AccumulateLine(Id," Anhydrite 0.0 1.0 ")
iphreeqc.AccumulateLine(Id,"REACTION_TEMPERATURE 1 ")
iphreeqc.AccumulateLine(Id," 25.0 75.0 in 50 steps ")
iphreeqc.AccumulateLine(Id,"SELECTED_OUTPUT ")
iphreeqc.AccumulateLine(Id," -file ex2.sel ")
iphreeqc.AccumulateLine(Id," -user_punch true ")
iphreeqc.AccumulateLine(Id," -reset false ")
iphreeqc.AccumulateLine(Id," -simulation false ")
iphreeqc.AccumulateLine(Id," -selected_out true ")
iphreeqc.AccumulateLine(Id," USER_PUNCH ")
iphreeqc.AccumulateLine(Id," -start ")
iphreeqc.AccumulateLine(Id," 10 punch - LA('H+') ")
iphreeqc.AccumulateLine(Id," -end ")
iphreeqc.AccumulateLine(Id,"END ")
# run model
runout=iphreeqc.RunAccumulated(Id)
estring2=iphreeqc.OutputErrorString(Id)
a=iphreeqc.GetSelectedOutputRowCount(Id)
b=iphreeqc.GetSelectedOutputColumnCount(Id)
print a
print b # this works, gives correct number of rows and columns
vart=VAR()
iphreeqc.VarInit(ctypes.byref(vart))
c=iphreeqc.GetSelectedOutputValue(Id, 43, 0, ctypes.byref(vart)) #tries to extract value from row 43, column 1
print c # c is here VRESULT. this works properly giving the right error number (0 to -6). Gives 0 in this case which is VR_OK
所选行、列中的值是double,但我也尝试过使用字符串值和long(整型)值,但没有成功。 我希望如此变量dVal(对于string或long,则为.sVal或lVal)以包含我想要的值,但它不是。 我也希望VAR_TYPE的TT_u字段中有一个是1,但它们都是0。 似乎.dVal、.sVal和.lVal实际上包含VAR_类型号(介于0和4之间),并且正确地报告了这一点(即3表示double类型,2表示long类型)。在
我的问题是:如何修复代码,使VAR_TYPE字段反映变量类型,而变量类型现在在.lVal字段中返回。 我怎样才能得到我想提取的正确值变量x值领域?在Python结构/联合代码中是否缺少一些指针?
结构和联合来自的C源(Var.h):
http://wwwbrr.cr.usgs.gov/projects/GWC_coupled/iphreeqc/Var_8h_source.html
我试图在Python中重现的C示例(v是Python代码中的变量'vart',我暂时忽略循环等):
^{pr2}$C示例取自:(向下滚动一点) http://wwwbrr.cr.usgs.gov/projects/GWC_coupled/iphreeqc/IPhreeqc_8h.html#a9f0ffd11e25a7e8f05d800623b14acf5
我在OSX10.6.6上使用的是cTypes1.1.0和Python2.6.6
很抱歉这个问题太长了,希望一些聪明人能帮我解决问题,或者给我指出正确的方向。在
非常感谢
一个问题是枚举不是结构。还要确保结构中的字段的顺序与C头的顺序相同(“type”排在第一位)。试试这个:
有一些短语(http://www.phreeqpy.com)可以解决您的问题。 免责声明:我是作者。在
PhreeqPy是IPhreeqc COM/DLL/共享库的包装器。 您应该通过Linux上的共享库或 Mac操作系统。在
以下是处理联合和结构的部分代码:
相关问题 更多 >
编程相关推荐