[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