Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

External File Attachment

dzallar
Beginner
2,139 Views
Hi All,
I am creating a console application using CVF 6.6C. This app uses a dll that reads data from previously written text files. These text files are set and do not change. When I distribute the application, I need to distribute the dll as well as the data files. I am wondering if there is a way to include these external data files either into the dll or the application I am creating so I only have to distribute the dll along with the exe. I have the source code for the dll if it needs to be changed.
Thanks,
David
0 Kudos
14 Replies
emc-nyc
Beginner
2,138 Views
"I am wondering if there is a way to include these external data files either into the dll or the application I am creating so I only have to distribute the dll along with the exe. I have the source code for the dll if it needs to be changed."

...

Yes. The details of how you would do this depend on the size and nature of the text files.

Case 1:
Files are small, and do not change.

Include them in the dll (or executable) as module variables. By small I mean up to about a megabyte or so. The code might be have a lot of lines to the effect of

CITY(45)%NAME = "San Francisco"
CITY(45)%STATE = "California"
CITY(45)%FOOTBALL = "Giants"
.
.
.
CITY(2443)%NAME = "West Overshoe"
...
in an initialization routine. It should be easy to write a script (in JavaScript, VBScript, perl, python, etc) to read the text files and convert them into appropriate Fortran code.

Case 2:
Files are large (several megabytes).
For this case, I recommend use of some sort of packager, or zipping or tarring them. If the end users aren't supposed to change the files, using encryption and check sums should provide adequate security. If they are allowed to change them, zipping or tarring are probably the easiest choice.

Case 3:

Files are small, and the users need access to them.

Add them to the executable or the dll. Add some code to write them to a known folder the first time the program runs, and check to see if these files are present on subsequent runs. You may have to write some information into an ini or .rc file or (Windows only!) into the registry so the program knows where to look.
0 Kudos
dzallar
Beginner
2,138 Views
Thanks for the reply. I think I like Case 3. And since I am somewhat still a novice at this, this seems to be the easiest option.
Thanks again.
0 Kudos
Jugoslav_Dujic
Valued Contributor II
2,138 Views
Basically, there's a way to add any file as a resource (into the "Resources" section of your dll) and extract it later. Searching...

See this thread. The attachment is below (because all attachments were recently screwed). Just unpack it, then run the executable -- you'll get the zip of the workspace itself :-).

Jugoslav
0 Kudos
dzallar
Beginner
2,138 Views
Jugoslav,
I am trying to recreate your example. I can recompile and the zip file is created but there is nothing in it. I'm not sure I understand how to manually edit the .rc file.
"The point is that you should edit the .rc file manually. Resource0001 is a resource type (user-defined), and USERDATA is the ID of the resource itself:

// RT_RCDATA
Resource0001 USERTYPE "ResExtract.f90""

When I use this and compile, the zip is created bu empty. Same if I use BINARYDATA "ResExtract_zip" "ResExtract.zip"

Any more help is appreciated.

David

0 Kudos
Jugoslav_Dujic
Valued Contributor II
2,138 Views
Sorry, that example was couple of years old. Basically, it's OK except for the following errors:

.rc line in question should read:


ResExtract_zip BINARYDATA "ResExtract.zip"


i.e. without quotes, while in code it should be:


hResource = FindResource(NULL, LOC("ResExtract_zip"C) &
LOC("BINARYDATA"C), )


i.e. the case doesn't matter but trailing "C" does :-).

Also, above I reversed the names to be more logical -- resource type is "BINARYDATA" and resource id is "ResExtract_zip".

Of course, the 3rd argument in .rc file is the name of the "source" file -- the one you're gonna pack into your executable(dll).

Jugoslav
0 Kudos
dzallar
Beginner
2,138 Views
It all makes sense now and it works.
David

Message Edited by dzallar on 09-16-2005 04:01 PM

Message Edited by dzallar on 09-16-2005 04:02 PM

Message Edited by dzallar on 09-16-2005 04:05 PM

0 Kudos
dzallar
Beginner
2,138 Views

Related Question. When the attached file is created it has today's date and time. Is there a way to stamp it with the original file's date and time stamp?

Thanks,

David

Message Edited by dzallar on 09-16-2005 04:07 PM

0 Kudos
Jugoslav_Dujic
Valued Contributor II
2,138 Views
Not automagically, because resource compiler strips off file information. You can reinstate it yourself using SetFileTime (+SystemTimeToFileTime) API, but that also means that you have to store the information yourself -- either hard-coded or as a string-table entry (LoadString).

Jugoslav
0 Kudos
dzallar
Beginner
2,138 Views

Thanks Jugoslav. I have added the following:

CALL PACKTIMEQQ (timedate, 2004, 07, 01,08, 12, 14)

result = SETFILETIMEQQ('mynewfile.txt', timedate)

It basically gives me the resluts I wanted. Do you see any problems using this method?

Thanks,

David

0 Kudos
Jugoslav_Dujic
Valued Contributor II
2,138 Views
No, you're fine -- these two have similar semantics as SystemTimeToFileTime and SetFileTime (probably just wrappers around them).

Jugoslav
0 Kudos
dzallar
Beginner
2,138 Views

Thanks again. As always, you are a big help.

David

0 Kudos
cacciatore
Beginner
2,138 Views
Hi,
I was able to insert a file (unformatted) as a resource, using
Jugoslav's method.
To use the data when running the .exe I used:

INTEGER FUNCTION WinMain
...
open(unit=1,file='c:mapa.bras',form='binary')
write(1)sVoidData(1:dwResourceSize)
close(1)
open(unit=1,file='c:mapa.bras',form='unformatted')
read(1)nupts
allocate(pontos(nupts,3))
read(1) pontos
close(1,disp='delete')
...
END FUNCTION WinMain

I would like to know how to get access to data (nupts and array pontos) without passing through the write(1)...close(1), by "reading directly" from memory.

Thanks
Geraldo Cacciatore
0 Kudos
Jugoslav_Dujic
Valued Contributor II
2,138 Views
But you already have it when you do the LockResource in the sVoidData array? The original question was about how to extract the file.

Of course, you don't have to use character or integer(1) array as the pointer type -- LockResource gives you a pointer to data, and you can set it to be any type you like. For example, if the original file was BINARY containing an array of REALs or a derived TYPE, simply set the pointer to appropriate type and there you get your data. If it was ASCII, you can get the data using a CHARACTER(LEN=enough) variable and parsing it (e.g. internal read).

Jugoslav

(Oh, the Forum again behaves, so your reply ended up in a wrong thread. Steve, since recently, sequence Open Thread+Reply+Log In leads to a blank "New message" page, and one must go few steps back & forward to reply to the intended thread. I'm curious why it wasn't reported & fixed so far.)
0 Kudos
cacciatore
Beginner
2,138 Views
Some of my 'windows' coding works (menytimes not) whithout really understanding what every piece of it means. I now see (true?) the file was inserted in the .exe by the MAPA BINARYDATA "C:EXEMAPA.BRAS" line in the .rc file.
Thank you very much

Geraldo
0 Kudos
Reply