Changes between Version 25 and Version 26 of SwiggingHlsvd


Ignore:
Timestamp:
Jul 14, 2009, 5:03:48 PM (10 years ago)
Author:
flip
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • SwiggingHlsvd

    v25 v26  
    184184{{{
    185185#!python
    186     yr = hlsvd_wrapper.new_float_array(2048)
    187     yi = hlsvd_wrapper.new_float_array(2048)
    188     ndata = hlsvd_wrapper.new_ndata()
    189     ndp = hlsvd_wrapper.new_ndp()
    190     tstep = hlsvd_wrapper.new_tstep()
    191     m = hlsvd_wrapper.new_m()
    192     nssv = hlsvd_wrapper.new_nssv()
    193     nit = hlsvd_wrapper.new_nit()
    194     rootr = hlsvd_wrapper.new_double_array(50)
    195     rooti = hlsvd_wrapper.new_double_array(50)
    196     fre = hlsvd_wrapper.new_float_array(50)
    197     dam = hlsvd_wrapper.new_float_array(50)
    198     amp = hlsvd_wrapper.new_float_array(50)
    199     phase = hlsvd_wrapper.new_float_array(50)
    200     sv = hlsvd_wrapper.new_double_array(1024)
    201     snoise = hlsvd_wrapper.new_snoise()
    202     rms = hlsvd_wrapper.new_rms()
    203     ndiv = hlsvd_wrapper.new_ndiv()
    204     nitf = hlsvd_wrapper.new_nitf()
     186yr = hlsvd_wrapper.new_float_array(2048)
     187yi = hlsvd_wrapper.new_float_array(2048)
     188ndata = hlsvd_wrapper.new_ndata()
     189ndp = hlsvd_wrapper.new_ndp()
     190tstep = hlsvd_wrapper.new_tstep()
     191m = hlsvd_wrapper.new_m()
     192nssv = hlsvd_wrapper.new_nssv()
     193nit = hlsvd_wrapper.new_nit()
     194rootr = hlsvd_wrapper.new_double_array(50)
     195rooti = hlsvd_wrapper.new_double_array(50)
     196fre = hlsvd_wrapper.new_float_array(50)
     197dam = hlsvd_wrapper.new_float_array(50)
     198amp = hlsvd_wrapper.new_float_array(50)
     199phase = hlsvd_wrapper.new_float_array(50)
     200sv = hlsvd_wrapper.new_double_array(1024)
     201snoise = hlsvd_wrapper.new_snoise()
     202rms = hlsvd_wrapper.new_rms()
     203ndiv = hlsvd_wrapper.new_ndiv()
     204nitf = hlsvd_wrapper.new_nitf()
    205205}}}
    206206
     
    209209{{{
    210210#!python
    211     hlsvd_wrapper.hlsvd(yr, yi, ndata, ndp, tstep, m, nssv,
    212                          rootr, rooti, fre, dam, amp, phase, sv, snoise,
    213                          rms, ndiv, nit, nitf)
    214 }}}
    215 
     211hlsvd_wrapper.hlsvd(yr, yi, ndata, ndp, tstep, m, nssv,
     212                    rootr, rooti, fre, dam, amp, phase, sv, snoise,
     213                    rms, ndiv, nit, nitf)
     214}}}
     215
     216{{{
     217#!rst
    216218Note that every disadvantage of the C interface remains. There's no distinction between input and output parameters. The complex numbers are still represented as correlated lists of floats. The list/array sizes must be specified explicitly, and an opportunity for memory corruption or a crash exists if one gets it wrong. One must keep track of which variables are floats and which are doubles. And it's many more lines of code than the Python version. (Some of this is exacerbated by ``hlsvd()``'s pass-by-reference interface.)
    217219
     
    233235
    234236One starts with the very unPythonic explicit load of the C library to be called:
    235 ::
    236 
    237     lib = ctypes.CDLL("hlsvd.dylib")
    238 
     237}}}
     238
     239{{{
     240#!python
     241lib = ctypes.CDLL("hlsvd.dylib")
     242}}}
    239243
    240244This is one place where SWIG is more Pythonic, since I access SWIG's library with a normal Python import statement.
     
    242246
    243247Ctypes already knows about, well, C types, so it's easy to create something that can be passed to a function expecting a C float, for instance:
    244 ::
    245 
    246    tstep = ctypes.c_float(.256)
    247 
     248
     249{{{
     250#!python
     251tstep = ctypes.c_float(.256)
     252}}}
    248253
    249254Arrays are pretty simple too:
    250 ::
    251 
    252    # Create an array type; this is like a class
    253    InputFloatArrayType = ctypes.c_float * 2048
    254    # Create an instance of that "class"
    255    yr = InputFloatArrayType()
    256 
     255
     256{{{
     257#!python
     258# Create an array type; this is like a class
     259InputFloatArrayType = ctypes.c_float * 2048
     260# Create an instance of that "class"
     261yr = InputFloatArrayType()
     262}}}
    257263
    258264The variable setup for the call to ``hlsvd()`` looks like the code below:
    259 ::
    260 
    261     InputFloatArrayType = ctypes.c_float * 2048
    262     OutputDoubleArrayType = ctypes.c_double * 50
    263     OutputFloatArrayType = ctypes.c_float * 50
    264 
    265     yr = InputFloatArrayType()
    266     yi = InputFloatArrayType()
    267 
    268     ndpmax = ctypes.c_long(2048)
    269     ndp = ctypes.c_long(1024)
    270     tstep = ctypes.c_float(.256)
    271     m = ctypes.c_long(380)
    272     nssv = ctypes.c_long(25)
    273     nit = ctypes.c_long(500)
    274 
    275     rootr = OutputDoubleArrayType()
    276     rooti = OutputDoubleArrayType()
    277     fre = OutputFloatArrayType()
    278     dam = OutputFloatArrayType()
    279     amp = OutputFloatArrayType()
    280     phase = OutputFloatArrayType()
    281     sv = OutputDoubleArrayType()
    282     snoise = ctypes.c_double()
    283     rms = ctypes.c_double()
    284     ndiv = ctypes.c_long()
    285     nitf = ctypes.c_long()
    286 
    287 
    288     lib.hlsvd(yr, yi, ctypes.byref(ndpmax), ctypes.byref(ndp),
    289                ctypes.byref(tstep), ctypes.byref(m), ctypes.byref(nssv),
    290                ctypes.pointer(rootr), ctypes.pointer(rooti),
    291                ctypes.pointer(fre), ctypes.pointer(dam),
    292                ctypes.pointer(amp), ctypes.pointer(phase),
    293                ctypes.pointer(sv), ctypes.pointer(snoise),
    294                ctypes.pointer(rms), ctypes.pointer(ndiv),
    295                ctypes.byref(nit), ctypes.pointer(nitf)
    296               )
    297 
     265
     266{{{
     267#!python
     268InputFloatArrayType = ctypes.c_float * 2048
     269OutputDoubleArrayType = ctypes.c_double * 50
     270OutputFloatArrayType = ctypes.c_float * 50
     271
     272yr = InputFloatArrayType()
     273yi = InputFloatArrayType()
     274
     275ndpmax = ctypes.c_long(2048)
     276ndp = ctypes.c_long(1024)
     277tstep = ctypes.c_float(.256)
     278m = ctypes.c_long(380)
     279nssv = ctypes.c_long(25)
     280nit = ctypes.c_long(500)
     281
     282rootr = OutputDoubleArrayType()
     283rooti = OutputDoubleArrayType()
     284fre = OutputFloatArrayType()
     285dam = OutputFloatArrayType()
     286amp = OutputFloatArrayType()
     287phase = OutputFloatArrayType()
     288sv = OutputDoubleArrayType()
     289snoise = ctypes.c_double()
     290rms = ctypes.c_double()
     291ndiv = ctypes.c_long()
     292nitf = ctypes.c_long()
     293
     294
     295lib.hlsvd(yr, yi, ctypes.byref(ndpmax), ctypes.byref(ndp),
     296           ctypes.byref(tstep), ctypes.byref(m), ctypes.byref(nssv),
     297           ctypes.pointer(rootr), ctypes.pointer(rooti),
     298           ctypes.pointer(fre), ctypes.pointer(dam),
     299           ctypes.pointer(amp), ctypes.pointer(phase),
     300           ctypes.pointer(sv), ctypes.pointer(snoise),
     301           ctypes.pointer(rms), ctypes.pointer(ndiv),
     302           ctypes.byref(nit), ctypes.pointer(nitf)
     303          )
     304}}}
    298305
    299306At first glance this might look no better than the SWIG code, but it's actually a bit nicer. For one thing, the array sizes are defined in one place (the first three lines) and not repeated over and over. In addition, it's pretty clear what's going on in a line like this:
    300 ::
    301 
    302     ndiv = ctypes.c_long()
     307
     308{{{
     309#!python
     310ndiv = ctypes.c_long()
     311}}}
    303312
    304313whereas SWIG's version is opaque:
    305 ::
    306 
    307     ndiv = hlsvd_wrapper.new_ndiv()
    308 
     314
     315{{{
     316#!python
     317ndiv = hlsvd_wrapper.new_ndiv()
     318}}}
    309319
    310320The ``ctypes.byref()`` call is informative. It says that the C interface demands that I pass by reference, but I don't need access to the pointer here in Python. That tells anyone reading this code that I probably don't care what the called function does with the value, hinting that it is input-only. Again, I wouldn't need this at all if the f2c-generated code was tweaked to eliminate the unnecessary pass-by-reference for the input parameters.