F# interactive throws NotImplementedException in PCLStorage - f#

I'm getting NotImplementedException trying to use PCLStorage.FileSystem.Current in F# interactive.
I downloaded PCLStorage with NuGet, right clicked on the reference and clicked "Send to F# interactive"
I'm working with VS2015 update 1, and I've re-installed the package as suggested in this answer
How can I get PCLStorage to work in F# interactive?
--> Referenced 'C:\Users\amade\Documents\GitHub\audioExperiments\src\Audio\packages\PCLStorage.1.0.2\lib\portable-net45+wp8+wpa81+win8+monoandroid+monotouch+Xamarin.iOS+Xamarin.Mac\PCLStorage.dll'
> open PCLStorage;;
> PCLStorage.FileSystem.Current;;
> System.NotImplementedException: This functionality is not implemented in the portable version of this assembly. You should reference the PCLStorage NuGet package from your main application project in order to reference the platform-specific implementation.
at PCLStorage.FileSystem.get_Current()
at <StartupCode$FSI_0017>.$FSI_0017.main#()
Stopped due to error

The PCL you've referenced is the one designed to target all platforms (Xamarin, Windows desktop, Windows phone etc). This dll is simply used as a means of defining all of the individual methods as part of the bait and switch PCL technique http://log.paulbetts.org/the-bait-and-switch-pcl-trick/ If you want to use the library with FSI then you'll need to add a specific reference to the appropriate platform's DLL. In this case you'll want to refer to the windows desktop version of the project which you downloaded from NuGet.

Related

Custom component dependency hell

I'm trying to make a package for a custom component I made. It's based on several libraries, including Graphics32, GraphicEx and CCR.Exif.
I created a Package project, wrote the unit including its Register procedure, added some extra references Delphi notified me about to the requires section (including dbrtl.dcp, inet.dcp, soaprtl.dcp, vclimg.dcp, xmlrtl.dcp and dclGraphicEx140.dcp) and added many units to the contains section to avoid warnings about it happening implicitly. The project compiles and can be installed and used on my own machine without issues. However, when I want to install it on another machine, the troubles begin. In the end, I had to copy about all DCUs from all 3rd party components I used, plus both the DCP and BPL from GraphicEx, which I had to install even.
Supplying a lot of files is a bummer, yet surmountable, but having to install other packages as well is a no go. I could get rid of that DCP and BPL by putting even more units in the contains section, but that resulted in error messages on my own machine where GraphicEx is actually installed. This is confusing to me, because with Graphics32 nothing like that occurs...
Anyway, how do I keep my distribution to a minimum and avoid such situations? I want other developers on my team to be able to use the package without worrying about what I used to build it. For a start, can't all the 3rd party units be compiled into my own DCU?
What you experienced is an usual thing to the ones who write components. The distribution is always like that. Packages do not carry other packages, insted they reference them. It´s in their nature.
In order to overcome such a situation I always treat my components in the same way I would if they were a product to sell: I build a setup wizard that distributes and registers everything the package needs.
In my case InnoSetup works very well (http://www.jrsoftware.org/isinfo.php).
Summary
Haven't use Delphi for a while, but, did develop my custom visual controls (Last version I work was Delphi 6).
There are 2 issues when dealing with packages dependencies. One is installing at the Delphi enviroment, making controls appear on the component palette, plus, component editors & property editors.
And another when distributing the compiled packages into customers machines.
It also depends, on which version on Delphi you are running.
Design Time
When developing a custom package, there is a tab for package options, that indicates the destination folders.
The manuals usually tell the developers to leave those textboxes empty. That sometimes works, sometimes doesn't. I explicity write each folder path, in the respective textbox.
There is a textbox path for the ".dcp" files, other for the ".dcu", and so on.
If you have visual controls and stuff like property editors or component editors, its better to split the code in 2 packages ("Runtime" & "Designtime").
I usually put the delphi (packages) projects outside the delphi installation folder.
Run Time
Usually, the quick way is to put the "*.bpl" ".dcp" files in the Windows (32) / system folder, or similar "DLL" windows folder.
Packages folder structure source code suggestion
Managing packages can be difficult. I don't know how much the installation process has changed with Embarcadero, and the newer versions of Delphi. The following chart,is an example on how organize the source code. Hope it helps.
[-]--+--c:
.....|
.....+--[-]--+--software
.............|
.............+--[+]-----java
.............|
.............+--[+]-----php
.............|
.............+--[-]--+--delphi (not the delphi folder in program files)
.....................|
.....................+--[+]-----apps (source code for delphi programs)
.....................|
.....................+--[+]-----other
.....................|
.....................+--[-]--+--packages (all delphi packages source code here)
.............................|
.............................+--[+]-----lib (a single package for non visual controls, libraries)
.............................|
.............................+--[+]-----tools (package pair for non visual tcomponent descendants)
.............................|
.............................+--[+]-----json (example)
.............................|
.............................+--[+]-----xml (example)
.............................|
.............................+--[-]--+--mycontrols (folder custom visual controls)
.............................|.......|
.............................|.......+--[-]--+--delphi40 (folder for delphi40 version of "mycontrols")
.............................|.......|.......|
.............................|.......|.......+----------dsgvclctrls40.dpk (design-time package "mycontrols")
.............................|.......|.......|
.............................|.......|.......+----------runvclctrls40.dpk (run-time package "mycontrols")
.............................|.......|.......|
.............................|.......|.......+--[+]--+--demos (individual example for each "mycontrol")
.............................|.......|.......|
.............................|.......|.......+--[+]--+--design ("*.pas" component editors destination folder)
.............................|.......|.......|
.............................|.......|.......+--[+]--+--sources ("*.pas" source code destination folder)
.............................|.......|.......|
.............................|.......|.......+--[+]--+--bin ("*.dcu" destination folder)
.............................|.......|........
.............................|.......+--[+]--+--delphi50 (folder for delphi50 version of "mycontrols")
.............................|.......|........
.............................|.......+--[+]--+--delphi60 (folder for delphi60 version of "mycontrols")
.............................|.......|........
.............................|.......+--[+]--+--delphi70 (folder for delphi70 version of "mycontrols")
.............................|................
.............................+--[-]-----etc...
Cheers.
Thijs, you simply cannot do that with only a package. The target developer will require almost everything you added to the package. But there is an alternate way of doing what you want: Build a DLL with all the components/libraries you are using in your own component and wrap all those external components/libraries into some code you will export from the DLL. Then build your component without using the external components directly but the DLL you've built. You cannot in you component "use" any unit of the other external components/Libraries. You have to build a new unit with all the datatypes and required declaration for anything you export from your DLL. All this is perfectly working but will quickly becomes very complex for a large number of external components or libraries.
I think AlexSC has the best answer, but I think there might be an alternative if you ansolutely must have a custom component that has no dependencies.
I ran into the Delphi dependency frustrations a little while back trying to create an in-house component for our developers. My suggestion:
Uninstall all dependencies your component uses
In your component package, remove the above dcp from the requires section from your package.
Copy the source files of your dependencies to your components
When you distribute the component, you'll have to distibute it with the code of the required dependecies
You'll run into issues if you want to use the dependcies separately since Delphi won't allow you to have duplicate unit names in installed packages.
Also, the reason you don't want to use DCUs is the fact that the DCUs are compiled for a specific platform and compiler. So unless you are sure that all devolpers are on the same platform ad using the same version of Delphi, dependency code needs to be recompiled.
Again, AlexSC has the best answer and InnoStudio is a great little tool.

Namespace or module "NagLibrary" not found, but reference successfully added (?)

I have a 3rd party .dll that I have successfully added as a reference in both a VS 2010 C# project and an F# VS 2010 project. I can view the contents in the object browser in both cases, but the F# version won't let me "open" the library. It works fine in the C# project (with the "using" directive), and I can write a program that uses the contents of this particular .dll. I have not had any trouble with other .dlls in F#/VS 2010/.NET 4.0 on Windows 7.
Any ideas as to why this might be happening? Or how I could debug this further?
See what the csc.exe and fsc.exe command-lines have for the library in question (in VS, open the 'Output Window' after a rebuild), to see if they both have the same reference (e.g. -r:Path\Library.dll).
And to be clear, you're saying
open NagLibrary
in F# yields the error message in the title, but
using NagLibrary;
in C# works and opens the namespace?
make sure you reference the path within the script using the double "\" convention
for me this worked
#r "C:\homeware\\blp\\api\\APIv3\\DotnetAPI\\v3.4.5.4\\lib\\Bloomberglp.Blpapi.dll"
open Bloomberglp.Blpapi

F# powerpack and distribution

I need arbitrary precision rational numbers, which I'm given to understand are available in the F# powerpack. My question is about the mechanics of distribution; my program needs to be able to compile and run both on Windows/.Net and Linux/Mono at least, since I have potential users on both platforms. As I understand it, the best procedure is:
Download the powerpack .zip, not the installer.
Copy the DLL into my program directory.
Copy the accompanying license file into my program directory, to make sure everything is above board.
Declare references and go ahead and use the functions I need.
Ship the above files along with my source and binary, and since the DLL uses byte code, it will work fine on any platform.
Is this the correct procedure? Am I missing anything?
You're essentially correct, arbitrary precision rational numbers are available only in PowerPack (BigInteger is part of .NET 4.0, but rationals are still F# specific).
However, you'll also need to distribute your program with F# runtime redistributable (that is the FSharp.Core.dll assembly). It contains some basic F# types (such as types used to represent functions) that are not a part of standard .NET runtime.
More information about F# Redistributable Package is available at MSDN
You can download the FSharp.Core.dll redist from Microsoft Downloads.
When you add a reference to your project, the compiler includes the name and version of the referenced library in your application. When the application starts, the runtime tries to locate the library in various places. So, to deploy your application on both .NET and Mono, you'll need to (somehow) distribute your application together with FSharp.Core.dll and FSharp.PowerPack.dll.
The F# Redistributable and F# PowerPack installers place the library to GAC (Global Assembly Cache) which is shared by all .NET apps on the computer. On Mono, you can get the same result by using the gacutil tool (from command line). In that case, you need to copy them somewhere (anywhere) and run this tool. Your application will find them in the GAC.
Alternatively, if you place the assemblies to the same folder as your application (exe file) then both .NET and Mono should locate them correctly as well and it should work. I believe that this is discouraged for versioning reasons (e.g. the globally installed file can be easily updated), but I don't think the license prohibits this form of deployment.
It seems that for creating .NET/Mono redistributable, using the second technique would be easier (as it allows simple xcopy depoloyment).

How do I unbind a library reference in F# interactive

In VS 2010 I reference several libraries using #r
Once I run an interactive session these libraries get bound. As a consequence I cannot rebuild my library because the system complains these libraries are currently used.
How do I unbind them in case I want to update the library?
A possible thing to try is the 'Reset Session' option in the FSI tool window. (I haven't tried this myself to see if it works.)

Seq.generate_using is MIA

I'm trying to use the Seq.generate_using function but unfortunately, I don't seem to be able to find it. I thought it would be living here:
Microsoft.FSharp.Collections.Seq.generate_using
But it doesn't. I am getting the error listed below.
C:\Users\Owner\Documents\Visual Studio
2008\Projects\fsharp1\Program.fs(54,63):
error FS0039: The value, constructor,
namespace or type 'generate_using' is
not defined. A construct with this
name was found in
FSharp.PowerPack.dll, which contains
some modules and types that were
implicitly referenced in some previous
versions of F#. You may need to add an
explicit reference to this DLL in
order to compile this code.
According to the Sept 2008 CTP Release Notes:
The F# library is split into two
components. FSharp.Core.dll: Contains
the core F# libraries, which will be
stabilized and versioned infrequently.
FSharp.PowerPack.dll: Contains
additional useful F# libraries and
tools which will version more
frequently, and allow continued
innovation on top of the core F#
language and libraries.
Some methods in the Seq module were moved into the FSharp.PowerPack assembly, so you can only get those methods by doing the following:
If you're using Visual Studio, open your Solution Explorer, right-click on the project file, choose "Add Reference", and add "FSharp.PowerPack.dll".
If you're using a script file or fsi, then type #r "FSharp.PowerPack";; to load the assembly.
Now you should be able to call Seq.generate_using.
The #r "FSharp.PowerPack";; works for me but the addition of PowerPack to my solution does not. I am trying to use HashSet<>.

Resources