[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