Is there a way to share types across fsx files?
When using #load to load the same file containing a type from multiple FSX files they seem to be prefixed into a different FS_00xx namespace each time, which means you can't pass them around.
Are there any ways around this behaviour without resorting to compiling into an assembly?
As for
http://msdn.microsoft.com/en-us/library/dd233169.aspx
[.fsx files are] used to include informal testing code in F# without adding the test code to your application, and without creating a separate project for it. By default, script files are not included in the build of a project even when they are part of a project.
This means that if you have a project with enough structure to be having such dependency problems, you should not use .fsx files, instead write modules/namespaces using .fs files. That is, you really should compile them types into an assembly.
The f# interactive interpreter generates assembly for each loaded files. If you load a file twice, the bytecode is generated twice, and the types are different even if they have the same definition and the same name. This means that there is no way for you to share types between two .fsx files, unless one of them includes the other.
When you #load a file which has the same types as ones already present in your environment, the f# interactive interpreter can use two different strategy:
refuse to load the file if conflicts with existing names arises (complaining that some stuff is already defined)
put the names in FS_00xx namespace (so that they are actually different types from the ones you already loaded), eventually opening the resulting namespace so that names are available from interactive session.
Since fsx files are supposed to be used as informal test it is more user-friendly to use the second approach (there are also technical reason for which the second approach is used, mainly dependent on .net VM type system, and the fact that existing types cannot be changed at runtime).
[Note: This is a more specific answer to a more specific question that is a duplicate of this one.]
I don't think there is a nice and easy solution for this. The one solution I have been using in some projects (like the F# snippets web site) is to have only one top-level fsx file that loads a number of fs files. For example, see app.fsx.
So, you would have common.fs, intMapper.fs and stringMapper.fs that would be loaded from caller.fsx as follows:
#load "common.fs"
#load "stringMapper.fs"
#load "intMapper.fs"
open Common
Inside stringMapper.fs and intMapper.fs, you do not load common.fs. The common types will be loaded by caller.fsx before, so things will work.
The only issue with this is that intMapper.fs now isn't a standalone script file - and if you want to get autocomplete in an editor, you need to add a fsproj file that specifies the file order. In F# snippets project, there is a project file which specifies the order in whch the editor should see and load the files.
Have all the #load and #open directives in the file you actually run from fsi.exe (C in the example below), and make sure the loaded files themselves do not #load their own dependencies:
Files A.fsx, B.fsx, C.fsx. B depends on A. C depends on B and A.
B contains
//adding the code below would cause the types defined in A to be loaded twice
//#load "A.fsx"
//#open A
C contains
#load "A.fsx"
#open A
#load "B.fsx"
#open B
Unfortunately this then makes all the files hard to edit from Visual Studio - the editor doesn't know about their dependencies and shows all sorts of errors.
Therefore this is a bit of a hack, and the recommended way seems to be to have a single .fsx file and compile everything else into a .dll :
// file1.fsx
#r "MyAssembly.dll"
https://msdn.microsoft.com/en-us/library/dd233175.aspx
Related
I have a legacy Windows project using the legacy 32 Bit C++ compiler. For various reasons I need to use the Windows 8+ function PathCchCanonicalizeEx. C++Builder seems to provide the header and some module definition file for that, but I can't find any library to link against:
[ilink32 Error] Error: Unresolved external 'PathCchCanonicalizeEx' referenced from C:\[...]\WIN32\DEBUG\TMP\FILE.OBJ
How am I supposed to fix this? Do I need to add a Windows 8.1 SDK? Is the necessary lib simply named differently and I can't find it? Something completely different?
According my tests, one has two options:
IMPLIB/MKEXP
I'm developing/testing a some Windows 10 21H2, which provides an implementation for PathCchCanonicalizeEx in some DLL already. So if that source DLL is known, one can use IMPLIB or MKEXP to create an import library manually. I did that and after adding the created library from IMPLIB to my project, the linker errors were instantly gone.
Though, it's not that easy to know where PathCchCanonicalizeEx is placed in. One pretty easily finds the api-ms-win-core-path-l1-1-0.dll, but that thing is NOT an actual file on the disk and therefore can't be used by IMPLIB or MKEXP. That name is only a virtual concept for the library loader to address the same named API set of modern Windows, the extension .dll doesn't mean it's a file at all.
You can use an API set name in the context of a loader operation such as LoadLibrary or P/Invoke instead of a DLL module name to ensure a correct route to the implementation no matter where the API is actually implemented on the current device. However, when you do this you must append the string .dll at the end of the contract name. This is a requirement of the loader to function properly, and is not considered actually a part of the contract name. Although contract names appear similar to DLL names in this context, they are fundamentally different from DLL module names and do not directly refer to a file on disk.
https://learn.microsoft.com/en-us/windows/win32/apiindex/windows-apisets#api-set-contract-names
What you really need to work with is KernelBase.dll, which is even documented by MS.
implib "KernelBase x86.lib" C:\Windows\SysWOW64\KernelBase.dll
implib "KernelBase x86-64.lib" C:\Windows\System32\KernelBase.dll
Module Definition File
The downside of manually creating LIB files is that one needs to maintain those with the project. Things depend on if the target is 32 or 64 Bit, DEBUG or RELEASE, so paths might become a bit complex, one might need to create relative paths for libraries in the project settings using placeholders for the target and stuff like that.
It seems that all of this can be avoided with Module Definition Files, which's purpose is to provide IMPORT and EXPORT statements to either consume exported functions by other DLLs or make that possible for others with own functions. I've successfully resolved my linker problems by simply creating a file named like my app using the extension .def alongside my other project files. That file needs to be added to the project, though.
dbxml.cbproj
dbxml.cbproj.local
dbxml.cpp
dbxml.def
dbxml.res
[...]
The following content made the app use the correct function from the correct DLL. Though, what didn't work was using the API set name, which resulted in an error message by the linker.
IMPORTS
KernelBase.PathCchCanonicalizeEx
IMPORTS
api-ms-win-core-path-l1-1-0.PathCchCanonicalizeEx
[ilink32 Error] Invalid command line switch for "ilink32". Parameter "ItemSpec" cannot be null.
[ilink32 Error] Fatal: Error processing .DEF file
The latter is after restarting C++Builder, so I guess the format of the file is simply wrong because of the API set name.
Delphi 10 Seattle introduces Winapi.Security.pas. The project (a package) I'm trying to upgrade already has a Security.pas file. Short of removing Winapi from the list of scope names for the project (huge undesirable ripple effect), is there a way to tell the IDE and compiler to use the project's Security.pas file instead of Winapi.Security.pas?
I already tried renaming the projects Security.pas, but that caused even more problems with the compiler generating errors that have nothing to do with the code it was complaining about, so that's a rathole I'd rather not go down right now. This project builds just fine unchanged in XE7, FWIW, so this isn't due to any code changes in the project.
Updates:
Renaming the file and using a unit alias doesn't work.
The compiler behavior for a package differs from an application.
Looks like this might actually be related to the Winapi.Security unit rather than something as generic as you suggest in the question. For instance, the following package compiles just fine:
package Package1;
requires
rtl;
contains
Windows in 'Windows.pas'; // blank unit named Windows.pas in project folder
end.
Note that I have, like you, included Winapi in the project's list of unit scope names.
On the other hand, this package does not compile:
package Package1;
requires
rtl;
contains
Security in 'Security.pas'; // blank unit named Security.pas in project folder
end.
The compiler fails with:
[dcc32 Error] Package1.dpk(7): E2200 Package 'rtl' already contains unit 'Winapi.Security'
If the issue was purely related to unit scope names then either both packages would compile, or both would fail. Hence my conclusion that there is something out of whack with Winapi.Security.
I can find no source code for Winapi.Security. I wonder what it actually is. [Nicholas Ring located the source for me, inside the rtl\win\winrt directory.]
Anyway, I think it's time to submit a QP report. The package below that fails to compile is probably the starting point for that QP report. [Your submitted report is here RSP-12469.]
It seems clear to me that in the short term you must rename your unit if you wish to adopt Seattle.
FWIW, here are some other units that behave the same way as Winapi.Security:
Winapi.ApplicationModel
Winapi.CommonTypes
Winapi.Devices
Winapi.Foundation
Winapi.Gaming
Winapi.Globalization
Winapi.GraphicsRT
Winapi.Management
Winapi.Media
Winapi.Networking
Winapi.Storage
Winapi.UI
Winapi.WebRT
These are all newly added WinRT units which I expect is important.
If you put both Winapi.Security and your local Security in the same uses clause then you are able to access the members of both of them without issue. If you put them in separate uses clauses (Interface vs. Implementation) then you will get the error:
E2004 Identifier redeclared: 'Winapi.Security'
If I only include Security.pas in the uses clause (and it is included in the project) then it accesses its members just fine.
Perhaps I need more information about what error you are running into? I'll send you a sample project that shows this working.
I might well be wrong, but I believe that if Security.pas is in the uses clause of the dpr file, along with its full path, it will be preferred over whichever file can be found via the namespaces and search paths.
Open project settings, in the Delphi Compiler section remove "Winapi" from "Unit scope names".
This way, when you need the Security unit shipped with Delphi, you'll have to write Winapi.Security, and if you write Security, it will use your custom Security unit.
I am aware that there are already other questions on the topic, such as:
This one
This one
This other one
.. but hey, I am new to F# and still don't get it.
I have a F# project (thelibrary) which contains some modules. This project references in the solution explorer all the necessary libraries. Each .fs file opens the libraries used in the module. The F# project compiles properly.
I have then another F# project which contains a script. I reference thelibrary and the libraries used by thelibrary itself. In the script I reference with #r the dll with thelibrary and all the libraries used by thelibrary. I then open all the modules.
Intellisense says all is allright until I execute the script.
The script returns the error:
error FS0074: The type referenced through 'Fmat.Numerics.Matrix`2' is defined in an assembly that is not referenced. You must add a reference to assembly 'Fmat.Numerics'.
What is the procedure to hack this problem? How do I proceed from there?
I am interested is a solution to this specific problem but, as well, a cookbook recipe to fix this type of issues that have been quite a source of frustration for me.
Thank you.
The behavior of F# Interactive can be a bit odd in this case. In general, I think that things work better when you use #I to include the path with referenced assemblies in the resolution context and then reference the libraries by name using #r. So if you have a library Fmat.Numerics.dll in a folder C:\libs and it references another library another.dll then you can do:
#I "C:\\libs"
#r "another.dll"
#r "Fmat.Numerics.dll`
The first line means that F# Interactive will automatically look in the folder with your libraries (this can be relative path to your script location too) - as a result, the next two lines can just reference the libraries by their file names.
This is still a problem. I can also reproduce and fix the problem as follows:
I have three projects:
Informedica.Settings.Library
Informedica.Settings.Services.Interfaces
Informedica.Settings.Services.Models
Project 2 uses project 1 and project 3. Project 1 uses project 3.
When I load the references in the order (first proj 3 then proj 1):
#r #"..\..\Informedica.Settings.Services.Models\bin\Release\Informedica.Settings.Services.Models.dll"
#r #"..\..\Informedica.Settings.Library\bin\Release\Informedica.Settings.Library.dll"
Everything works. Unfortunately, when I use the VS2013 send references to fsi or use the new power tools generate references option, the order is:
#r #"..\..\Informedica.Settings.Library\bin\Release\Informedica.Settings.Library.dll"
#r #"..\..\Informedica.Settings.Services.Models\bin\Release\Informedica.Settings.Services.Models.dll"
This will result in the FS0074 error. Apparently, because a type from Services.Models is used in Settings.Library and the order of reference is reversed, fsi cannot handle this. Correcting the order of referencing solves the problem.
Running things in fsi does not add references from the project, you need to use #r .... The error message is reasonably obvious in what you need to do - add a reference to Fmat.Numerics. It is also possible that you have such a reference, but that fsi is sensitive to the load order.
Beyond allowing one file to use another file's attributes, what actually happens behind the scenes? Does it just provide the location to access to that file when its contents are later needed, or does it load the implementation's data into memory?
In short;
The header file defines the API for a module. It's a contract listing which methods a third party can call. The module can be considered a black box to third parties.
The implementation implements the module. It is the inside of the black box. As a developer of a module you have to write this, but as a user of a third party module you shouldn't need to know anything about the implementation. The header should contain all the information you need.
Some parts of a header file could be auto generated - the method declarations. This would require you to annotate the implementation as there are likely to be private methods in the implementation which don't form part of the API and don't belong in the header.
Header files sometimes have other information in them; type definitions, constant definitions etc. These belong in the header file, and not in the implementation.
The main reason for a header is to be able to #include it in some other file, so you can use the functions in one file from that other file. The header includes (only) enough to be able to use the functions, not the functions themselves, so (we hope) compiling it is considerably faster.
Maintaining the two separately most results from nobody ever having written an editor that automates the process very well. There's not really a lot of reason they couldn't do so, and a few have even tried to -- but the editors that have done so have never done very well in the market, and the more mainstream editors haven't adopted it.
Well i will try:
Header files are only needed in the preprocessing phase. Once the preprocessor is done with them the compiler never even sees them. Obviously, the target system doesn't need them either for execution (the same way .c files aren't needed).
Instead libraries are executed during the linking phase.If a program is dynamically linked and the target environment doesn't have the necessary libraries, in the right places, with the right versions it won't run.
In C nothing like that is needed since once you compile it you get native code. The header files are copy pasted when u #include it . It is very different from the byte-code you get from java. There's no need for an interpreter(like the JVM): you just feed it your binary stuff to the CPU and it does its thing.
J2ME lacks the java.util.Properties class. Although it is possible to put application settings in the JAD file this is not recommended for many properties. (Since, some platforms limits the size of JAD file.) I want to put a configuration file inside my jar file and parse it. And I do not want to go with XML because it will be overshooting for my case.
Question is, is there an already existing library for J2ME that can parse properties files or something similar such as INI file. Or would you recommend another method to solve the initial problem?
The best solution probably depends on what is going to be generating the properties files.
If you've got other non-JavaME projects using the same properties files, then stick with them, and write or find a parser. (There is a simple one from GoBible available on Google Code)
However you might find it just as easy to keep your configuration as static final String myproperty="myvalue"; in a Configuration.java file which you compile, and include in the jar instead, since you then do not need any special code to locate, open, read, and parse them.
You do then pick up a limitation on what you call them though, since you can no longer use the common dot separated namespacing idiom.