De : keilholz, werner
Mark, You can use the Special cards
for that, you may just have to add the declaration of the function to access
the special cards to Trnsys.h (it is not declared there by default). In this
case, you should not declare the file as an “External file” in the
PROFORMA, and handle opening and closing it yourself, as you suggested. This is a bit
complicated, due to the way strings are handled in FORTRAN ; I’ve
described the principle for the MESSAGE function here: https://www-old.cae.wisc.edu/pipermail/trnsys-users/2009/004778.html Werner De :
Mark.Goldsworthy@csiro.au [mailto:Mark.Goldsworthy@csiro.au] Werner, Thanks for your help. I have implemented
your code below and downloaded the header files and I can get it to compile. I
think it opens the file but doesn't read any lines (prints "null").
Using the labels (special cards) seems
like a good way to do this but I could not get this to work (please see my code
in the previous email). It seems to me that a much simpler
solution is to use the labels anyway -> could you please tell me what I am
doing wrong with that? Thank you Mark From:
keilholz, werner [mailto:werner.keilholz@cstb.fr] Hi, I had a similar problem
once concerning using external files from C and proposed a solution in the mail
below; maybe it is of use for you. TRNSYS 17 should introduce a new FILE
keyword to solve this problem more properly.
--- Reading TRNSYS external
files from C or C++ is somewhat tricky. The problem comes from
the fact that a) the TRNSYS kernel (not the TYPE) will open the
external file at the beginning of the simulation and (assign file handles) b) file handles are not interoperable between
compilers (sometimes not even between the release and debug version of the same
FORTRAN compiler) To work around the
problem, it has been proposed to use the special cards mechanism instead:
Recently, I implemented
another method to use ‘real’ external files with TYPES written in
C/C++. It is way bizarre, but works:
I provided the
FileReader.DLLs for those who do not have a FORTRAN compiler and the C++ code
implementing a class to access it follows (made with Compaq Visual FORTRAN for
compatibility with the official TRNSYS 16.1 release): ftp://ftp.cstb.fr/software/Trnsys/FileReader/ With this, you can just
read the file in C++ like this:
double
LUN;
LUN=par[0];
iunit=info[0];
itype=info[1];
std::string code;
TrnsysFileReader theReader;
while
(!theReader.Eof())
{
string tmp = theReader.ReadNextLine((int)
LUN);
code.append(rtrim(tmp));
code.append("\r\n");
} Hope this helps, Werner #include <cmath> #include <fstream> //#include
"windows.h" #include "TrnsysFileReader.h"
typedef int (__cdecl* LPFNDLLFUNC1)(int*); LPFNDLLFUNC1 lpfnDllFunc1; TrnsysFileReader::TrnsysFileReader() {
lpfProcFunction = NULL;
TCHAR path[1024];
GetModuleFileName(NULL, path, sizeof(path));
std::string str = path;
unsigned tmp1, tmp2;
tmp1 = tmp2 = 0;
for(unsigned i = 0; i < str.length(); i++)
{
if(path[i] == '\\')
{
tmp2 = tmp1;
tmp1 = i;
}
}
str.resize(tmp2);
#ifdef _DEBUG
str.append("\\Userlib\\DebugDLLs\\FileReader.dll");
#else
str.append("\\Userlib\\ReleaseDLLs\\FileReader.dll");
#endif
hLibrary = LoadLibrary(str.c_str());
eof = false;
maxFileWidth=1000; // from
TrnsysConstants.f90
} TrnsysFileReader::~TrnsysFileReader()
{
FreeLibrary(hLibrary);
}
bool TrnsysFileReader::Eof()
{
return eof;
}
int
TrnsysFileReader::ReadNextChar(int
LUN)
{
int c;
if (hLibrary == NULL) return -1;
lpfnDllFunc1 = (LPFNDLLFUNC1) GetProcAddress( hLibrary,
"READNEXTCHAR");
int
ilun = (int) LUN; c =
lpfnDllFunc1(&ilun);
if(c == -2) throw std::bad_exception("Problème avec le
fichier"); if
(c == -1) eof = true;
return c;
}
std::string TrnsysFileReader::ReadFile(int LUN)
{
std::string result;
char c;
while ((c =
ReadNextChar(LUN)) && (!eof))
{
std::string s;
s.append(&c,1);
result.append(s);
}
return result;
}
std::string TrnsysFileReader::ReadNextLine(int LUN)
{
std::string result;
char c;
while ((c =
ReadNextChar(LUN)) && (!eof) && (result.length() < (unsigned int)maxFileWidth-1))
{
std::string s;
s.append(&c,1);
result.append(s);
}
return result;
} TrnsysFileReader.h : #ifndef trnsyfilereaderincluded #define trnsyfilereaderincluded #include <cmath> #include <fstream> #include "windows.h" #include <string.h> #include "TRNSYS.h"
//TRNSYS acess functions (allow to
acess TIME etc.) typedef int (__cdecl* LPFNDLLFUNC1)(int*); class TrnsysFileReader { private :
HMODULE hLibrary;
FARPROC lpfProcFunction;
bool eof;
LPFNDLLFUNC1 lpfnDllFunc1;
int maxFileWidth; public:
TrnsysFileReader();
~TrnsysFileReader();
bool Eof();
int ReadNextChar(int LUN);
std::string ReadNextLine(int
LUN);
std::string ReadFile(int
LUN); }; #endif De :
Mark.Goldsworthy@csiro.au [mailto:Mark.Goldsworthy@csiro.au] Hi, I have read some posts on passing file names or labels to
C++ TRNSYS types but I don't think this question has been definitively
answered. This is what I have done: In the TRNSYS.h file I have the following lines which map
the fortran functions to C: extern "C" __declspec(dllimport) char*
_cdecl TRNSYSFUNCTIONS_mp_GETLUFILENAME(int* LU); Then
in the type I have: char *ss, *ss2; This code works (doesn't crash) but prints to the log file: "Label not available" "Cannot find a file associated with that
logical unit" I did link the file, logical unit and labels correctly
in the proforma so that is not the problem. Does anyone know what I am doing wrong? Thanks, Mark |