Skip to main content

Cross-version compatibility of LibraryLink libraries


I am looking for practical advice on the cross-version compatibility of LibraryLink libraries.


In particular, I would like to understand the significance of the WolframLibraryVersion define, which is normally returned from the WolframLibrary_getVersion function manually (meaning that one can in principle return whatever).


Under what circumstances will libraries compiled with an old version of Mathematica fail to load in a new version?


When will libraries compiled with a new Mathematica fail to load in an old Mathematica?


Does Wolfram provide any guarantees for binary compatibility? What about source compatibility?



Why is there a version value for WolframLibrary.h, but not for any of the ancillary headers like WolframSparseLibrary.h? Note that WolframLibraryVersion was not increased when new ancillary headers were added.


Particular concerns:




  • Changes in WolframLibraryVersion (e.g. it changed from 3 to 4 between 11.1 and 11.2)




  • New features introduced (e.g. the WolframRawArrayLibrary.h was introduced in 10.4)





  • Changes in external dependencies (e.g. on OS X, M10.4 uses libc++, while previous versions used the incompatible libstdc++)





Answer



We cannot guarantee binary compatibility across versions, especially if using C++. Given that MSFT didn't even attempt to have cross-version compatibility across Visual C++ version until VS2017 (with a special pragma to refuse to even try to link against different versions), there isn't much we can do about it. We do make every effort to maintain that compatibility.


Generally speaking, a new version of Mathematica can load old versions unless there is a C++ runtime incompatibility. Old version can load newer version as long as their is neither a C++ rumtime incompatibility or a source-level incompatibility (e.g., it is using a new interface). I'm not knowledgeble enough about the guts of LibraryLink to tell you why the library version was bumped or its significance--I would have that it is the API level. I'll ask some folk to take a look.


For the libstdc++ vs libc++ issue specifically, the resolution is easy. Build the library twice, once against libstdc++ and libc++, then load the correct version based on $VersionNumber at runtime. This is what we did for example with GitLink, so that can serve as a useful reference.


mlobjfile = FileNameJoin[{$InstallationDirectory,
"SystemFiles/Links/MathLink/DeveloperKit/MacOSX-x86-64",
"CompilerAdditions/mathlink.framework/Versions/4.25/mathlink"}];

compileOpts = StringReplace[compileOpts, "10.9"->"10.7"] <> " -Wl,\"" <> mlobjfile <> "\"";

This links against the the libstdc++-based version of MathLink, and it changes the -mmacosx-version-min from 10.9 to 10.7, which effectively changes the C++ runtime to link against.


This in principle generalizes as long as you keep your old M-'s around. Build duplicate libraries in older versions, copy them under a new name into your application, and load the correct one based on versions. You could theoretically do this with API-level incompatibilities using appropriate #ifdefs, but I this isn't something I've seen done.


In version 11.2, we (finally) transitioned away from VS2013 to VS2017. So you may find you need to build a new version of the shared library for Windows. In this case, you may need both an old M- and an old VS to do the build.


Comments

Popular posts from this blog

plotting - Filling between two spheres in SphericalPlot3D

Manipulate[ SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, Mesh -> None, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], {n, 0, 1}] I cant' seem to be able to make a filling between two spheres. I've already tried the obvious Filling -> {1 -> {2}} but Mathematica doesn't seem to like that option. Is there any easy way around this or ... Answer There is no built-in filling in SphericalPlot3D . One option is to use ParametricPlot3D to draw the surfaces between the two shells: Manipulate[ Show[SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], ParametricPlot3D[{ r {Sin[t] Cos[1.5 Pi], Sin[t] Sin[1.5 Pi], Cos[t]}, r {Sin[t] Cos[0 Pi], Sin[t] Sin[0 Pi], Cos[t]}}, {r, 1, 2 - n}, {t, 0, Pi}, PlotStyle -> Yellow, Mesh -> {2, 15}]], {n, 0, 1}]

plotting - Plot 4D data with color as 4th dimension

I have a list of 4D data (x position, y position, amplitude, wavelength). I want to plot x, y, and amplitude on a 3D plot and have the color of the points correspond to the wavelength. I have seen many examples using functions to define color but my wavelength cannot be expressed by an analytic function. Is there a simple way to do this? Answer Here a another possible way to visualize 4D data: data = Flatten[Table[{x, y, x^2 + y^2, Sin[x - y]}, {x, -Pi, Pi,Pi/10}, {y,-Pi,Pi, Pi/10}], 1]; You can use the function Point along with VertexColors . Now the points are places using the first three elements and the color is determined by the fourth. In this case I used Hue, but you can use whatever you prefer. Graphics3D[ Point[data[[All, 1 ;; 3]], VertexColors -> Hue /@ data[[All, 4]]], Axes -> True, BoxRatios -> {1, 1, 1/GoldenRatio}]

plotting - Mathematica: 3D plot based on combined 2D graphs

I have several sigmoidal fits to 3 different datasets, with mean fit predictions plus the 95% confidence limits (not symmetrical around the mean) and the actual data. I would now like to show these different 2D plots projected in 3D as in but then using proper perspective. In the link here they give some solutions to combine the plots using isometric perspective, but I would like to use proper 3 point perspective. Any thoughts? Also any way to show the mean points per time point for each series plus or minus the standard error on the mean would be cool too, either using points+vertical bars, or using spheres plus tubes. Below are some test data and the fit function I am using. Note that I am working on a logit(proportion) scale and that the final vertical scale is Log10(percentage). (* some test data *) data = Table[Null, {i, 4}]; data[[1]] = {{1, -5.8}, {2, -5.4}, {3, -0.8}, {4, -0.2}, {5, 4.6}, {1, -6.4}, {2, -5.6}, {3, -0.7}, {4, 0.04}, {5, 1.0}, {1, -6.8}, {2, -4.7}, {3, -1.