[Tutor] Accessing a DLL from python

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


Can anyone perhaps suggest the easiest way of translating the C code
into Python, bearing in mind that I'm rather a beginner?

Thanks
Hanlie

2011/3/1, Hanlie Pretorius <hanlie.pretorius at gmail.com>:
> 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