[Tutor] Accessing a DLL from python

Hanlie Pretorius hanlie.pretorius at gmail.com
Tue Mar 1 13:22:26 CET 2011


I see that I have misread the manual and that I need to reproduce the
code in the C example in python. The SWMM DLL doesn't contain
ready-made functions to open files etc.

Apologies for posting before I was completely sure of the problem.

Hanlie

2011/3/1, Hanlie Pretorius <hanlie.pretorius at gmail.com>:
> Hi Python Tutors,
>
> I'm using a storm water modelling program, EPA SWMM, to model the
> hydrology and hydraulics of a study area.
>
> SWMM reports its results in a binary (.out) file that contains the
> results for each element in the model at each time step in the model
> run. According to the SWMM interface manual
> (http://www.epa.gov/ednnrmrl/models/swmm/swmm5_iface.zip), one can use
> a DLL file to read the .out file. I want to do this so that I can read
> the state of a river at a specific time and plot its water level in a
> GIS.
>
> After some searching on the Internet, I came across ctypes, which I
> have tried. According to the SWMM manual:
>
> [manual]
> Opening the Output File
> ----------------------------------
> A function named OpenSwmmOutFile(outFile) that performs these tasks is
> contained in the example code files that accompany this guide. The
> argument to the function is the name of the binary output file. The
> return value from the function is an integer code with the following
> meanings:
> 0 - the run was successful
> 1 - the run was terminated with an error
> 2 - the output file could not be opened.
> [/manual]
>
> So, I tried the following python code:
> [code]
> In [14]: swmmdll =
> cdll.LoadLibrary("C:\\Hanlie\\model\\SWMM\\swmm5_0_018.dll")
>
> In [15]: results_file="C:\\Hanlie\\model\\SWMM\\c83a_v0\\c83a_v0.3.out"
>
> In [16]: open_file=swmmdll.OpenSwmmOutFile(results_file)
> ------------------------------------------------------------
> Traceback (most recent call last):
>   File "<ipython console>", line 1, in <module>
>   File "C:\Python26\lib\ctypes\__init__.py", line 366, in __getattr__
>     func = self.__getitem__(name)
>   File "C:\Python26\lib\ctypes\__init__.py", line 371, in __getitem__
>     func = self._FuncPtr((name_or_ordinal, self))
> AttributeError: function 'OpenSwmmOutFile' not found
> [/code]
>
> Can anyone perhaps help me to access the functions in this DLL?
>
> The manual also states:
> [manual]
> The following files are needed for applications that call functions
> from the swmm5.dll library:
> · swmm5.h for C/C++ applications
>  · swmm5.bas for Visual Basic applications
>  · swmm5.pas for Delphi applications.
> [/manual]
>
> And they give an example in C, Basic and Pascal to use the interface.
> I have appended the C example to this message.
>
> Thanks
> Hanlie
>
> [code]
> // swmm5_iface.c
> //
> // Example code for interfacing SWMM 5 with C/C++ programs.
> //
> // Remember to #include the file swmm5_iface.h in the calling program.
>
> #include <stdio.h>
> #include <windows.h>
> #include "swmm5.h"
>
> int    SWMM_Nperiods;                  // number of reporting periods
> int    SWMM_FlowUnits;                 // flow units code
> int    SWMM_Nsubcatch;                 // number of subcatchments
> int    SWMM_Nnodes;                    // number of drainage system nodes
> int    SWMM_Nlinks;                    // number of drainage system links
> int    SWMM_Npolluts;                  // number of pollutants tracked
> double SWMM_StartDate;                 // start date of simulation
> int    SWMM_ReportStep;                // reporting time step (seconds)
>
> int    RunSwmmExe(char* cmdLine);
> int    RunSwmmDll(char* inpFile, char* rptFile, char* outFile);
> int    OpenSwmmOutFile(char* outFile);
> int    GetSwmmResult(int iType, int iIndex, int vIndex, int period,
> float* value);
> void   CloseSwmmOutFile(void);
>
> static const int SUBCATCH = 0;
> static const int NODE     = 1;
> static const int LINK     = 2;
> static const int SYS      = 3;
> static const int RECORDSIZE = 4;       // number of bytes per file record
>
> static int SubcatchVars;               // number of subcatch reporting
> variables
> static int NodeVars;                   // number of node reporting
> variables
> static int LinkVars;                   // number of link reporting
> variables
> static int SysVars;                    // number of system reporting
> variables
>
> static FILE*  Fout;                    // file handle
> static int    StartPos;                // file position where results start
> static int    BytesPerPeriod;          // bytes used for results in each
> period
> static void   ProcessMessages(void);
>
> //-----------------------------------------------------------------------------
> int RunSwmmExe(char* cmdLine)
> //-----------------------------------------------------------------------------
> {
>   int exitCode;
>   STARTUPINFO si;
>   PROCESS_INFORMATION  pi;
>
>   // --- initialize data structures
>   memset(&si, 0, sizeof(si));
>   memset(&pi, 0, sizeof(pi));
>   si.cb = sizeof(si);
>   si.wShowWindow = SW_SHOWNORMAL;
>
>   // --- launch swmm5.exe
>   exitCode = CreateProcess(NULL, cmdLine, NULL, NULL, 0,
> 			 0, NULL, NULL, &si, &pi);
>
>   // --- wait for program to end
>   exitCode = WaitForSingleObject(pi.hProcess, INFINITE);
>
>   // --- retrieve the error code produced by the program
>   GetExitCodeProcess(pi.hProcess, &exitCode);
>
>   // --- release handles
>   CloseHandle(pi.hProcess);
>   CloseHandle(pi.hThread);
>   return exitCode;
> }
>
>
> //-----------------------------------------------------------------------------
> int RunSwmmDll(char* inpFile, char* rptFile, char* outFile)
> //-----------------------------------------------------------------------------
> {
>   int err;
>   double elapsedTime;
>
>   // --- open a SWMM project
>   err = swmm_open(inpFile, rptFile, outFile);
>   if (!err)
>   {
>     // --- initialize all processing systems
>     err = swmm_start(1);
>     if (err == 0)
>     {
>       // --- step through the simulation
>       do
>       {
>         // --- allow Windows to process any pending events
>         ProcessMessages();
>
>         // --- extend the simulation by one routing time step
>         err = swmm_step(&elapsedTime);
>
>         /////////////////////////////////////////////
>         // --- call progress reporting function here,
>         //     using elapsedTime as an argument
>         /////////////////////////////////////////////
>
>       } while (elapsedTime > 0.0 && err == 0);
>
>       // --- close all processing systems
>       swmm_end();
>     }
>   }
>
>   // --- close the project
>   swmm_close();
>   return err;
> }
>
>
> //-----------------------------------------------------------------------------
> void ProcessMessages(void)
> //-----------------------------------------------------------------------------
> {
>
> /****  Only use this function with a Win32 application *****
>   MSG msg;
>   while (TRUE)
>   {
>     if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
>     {
>       if (msg.message == WM_QUIT) break;
>       else
>       {
>         TranslateMessage(&msg);
>         DispatchMessage(&msg);
>       }
>     }
>     else break;
>   }
> ***********************************************************/
>
> }
>
>
> //-----------------------------------------------------------------------------
> int OpenSwmmOutFile(char* outFile)
> //-----------------------------------------------------------------------------
> {
>   int magic1, magic2, errCode, offset, offset0, version;
>   int err;
>
>   // --- open the output file
>   Fout = fopen(outFile, "rb");
>   if (Fout == NULL) return 2;
>
>   // --- check that file contains at least 14 records
>   fseek(Fout, 0L, SEEK_END);
>   if (ftell(Fout) < 14*RECORDSIZE)
>   {
>     fclose(Fout);
>     return 1;
>   }
>
>   // --- read parameters from end of file
>   fseek(Fout, -5*RECORDSIZE, SEEK_END);
>   fread(&offset0, RECORDSIZE, 1, Fout);
>   fread(&StartPos, RECORDSIZE, 1, Fout);
>   fread(&SWMM_Nperiods, RECORDSIZE, 1, Fout);
>   fread(&errCode, RECORDSIZE, 1, Fout);
>   fread(&magic2, RECORDSIZE, 1, Fout);
>
>   // --- read magic number from beginning of file
>   fseek(Fout, 0L, SEEK_SET);
>   fread(&magic1, RECORDSIZE, 1, Fout);
>
>   // --- perform error checks
>   if (magic1 != magic2) err = 1;
>   else if (errCode != 0) err = 1;
>   else if (SWMM_Nperiods == 0) err = 1;
>   else err = 0;
>
>   // --- quit if errors found
>   if (err > 0 )
>   {
>     fclose(Fout);
>     Fout = NULL;
>     return err;
>   }
>
>   // --- otherwise read additional parameters from start of file
>   fread(&version, RECORDSIZE, 1, Fout);
>   fread(&SWMM_FlowUnits, RECORDSIZE, 1, Fout);
>   fread(&SWMM_Nsubcatch, RECORDSIZE, 1, Fout);
>   fread(&SWMM_Nnodes, RECORDSIZE, 1, Fout);
>   fread(&SWMM_Nlinks, RECORDSIZE, 1, Fout);
>   fread(&SWMM_Npolluts, RECORDSIZE, 1, Fout);
>
>   // Skip over saved subcatch/node/link input values
>   offset = (SWMM_Nsubcatch+2) * RECORDSIZE  // Subcatchment area
>              + (3*SWMM_Nnodes+4) * RECORDSIZE  // Node type, invert & max
> depth
>              + (5*SWMM_Nlinks+6) * RECORDSIZE; // Link type, z1, z2,
> max depth & length
>   offset = offset0 + offset;
>   fseek(Fout, offset, SEEK_SET);
>
>   // Read number & codes of computed variables
>   fread(&SubcatchVars, RECORDSIZE, 1, Fout); // # Subcatch variables
>   fseek(Fout, SubcatchVars*RECORDSIZE, SEEK_CUR);
>   fread(&NodeVars, RECORDSIZE, 1, Fout);     // # Node variables
>   fseek(Fout, NodeVars*RECORDSIZE, SEEK_CUR);
>   fread(&LinkVars, RECORDSIZE, 1, Fout);     // # Link variables
>   fseek(Fout, LinkVars*RECORDSIZE, SEEK_CUR);
>   fread(&SysVars, RECORDSIZE, 1, Fout);     // # System variables
>
>   // --- read data just before start of output results
>   offset = StartPos - 3*RECORDSIZE;
>   fseek(Fout, offset, SEEK_SET);
>   fread(&SWMM_StartDate, sizeof(double), 1, Fout);
>   fread(&SWMM_ReportStep, RECORDSIZE, 1, Fout);
>
>   // --- compute number of bytes of results values used per time period
>   BytesPerPeriod = 2*RECORDSIZE +      // date value (a double)
>                    (SWMM_Nsubcatch*SubcatchVars +
>                     SWMM_Nnodes*NodeVars+
>                     SWMM_Nlinks*LinkVars +
>                     SysVars)*RECORDSIZE;
>
>   // --- return with file left open
>   return err;
> }
>
>
> //-----------------------------------------------------------------------------
> int GetSwmmResult(int iType, int iIndex, int vIndex, int period, float*
> value)
> //-----------------------------------------------------------------------------
> {
>   int offset;
>
>   // --- compute offset into output file
>   *value = 0.0;
>   offset = StartPos + (period-1)*BytesPerPeriod + 2*RECORDSIZE;
>   if ( iType == SUBCATCH )
>   {
>     offset += RECORDSIZE*(iIndex*SubcatchVars + vIndex);
>   }
>   else if (iType == NODE)
>   {
>     offset += RECORDSIZE*(SWMM_Nsubcatch*SubcatchVars +
>                           iIndex*NodeVars + vIndex);
>   }
>   else if (iType == LINK)
>   {
>     offset += RECORDSIZE*(SWMM_Nsubcatch*SubcatchVars +
>                           SWMM_Nnodes*NodeVars +
>                           iIndex*LinkVars + vIndex);
>   }
>   else if (iType == SYS)
>   {
>     offset += RECORDSIZE*(SWMM_Nsubcatch*SubcatchVars +
>                           SWMM_Nnodes*NodeVars +
>                           SWMM_Nlinks*LinkVars + vIndex);
>   }
>   else return 0;
>
>   // --- re-position the file and read the result
>   fseek(Fout, offset, SEEK_SET);
>   fread(value, RECORDSIZE, 1, Fout);
>   return 1;
> }
>
>
> //-----------------------------------------------------------------------------
> void CloseSwmmOutFile(void)
> //-----------------------------------------------------------------------------
> {
>   if (Fout != NULL)
>   {
>     fclose(Fout);
>     Fout = NULL;
>   }
> }
> [/code]
>


More information about the Tutor mailing list