3
$\begingroup$

I have a library function that need to load some external data files. But it looks that the path in the default path of library function is the path that Mathematica is currently in.

Is there a way to make a dynamic library that use the current path as the default path?

Here is an example:

Consider a library function that reads a integer from the file example.txt, which is at the same directory as the dynamic library files. The example.txt contains only one integer number in it:

cat example.txt
20

And here is the source of the library function:

#include "WolframLibrary.h"
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>

using namespace std;

DLLEXPORT mint WolframLibrary_getVersion(){
  return WolframLibraryVersion;
}
DLLEXPORT int WolframLibrary_initialize(WolframLibraryData libData){
  return 0;
}

EXTERN_C DLLEXPORT int readstring(WolframLibraryData libData, mint Argc, MArgument* Args, MArgument Res)
{
  int a;
  string line;

  ifstream file("example.txt");

  getline(file,line);
  istringstream iss(line);
  iss>>a;

  MArgument_setInteger(Res, a);
  return LIBRARY_NO_ERROR;
}

In the above code, the ifstream file("example.txt") tries to load a file that at the same directory as the library file, but since the current directory is the directory of Mathematic, it cannot find the file example.txt and will crash the kernel.

There are two solutions that I know:

  1. Use absolute path. For example change

ifstream file("example.txt")

to something like

ifstream file("/Users/xslittlegrass/example.txt")

  1. Change the current directory of Mathematica by something like

    SetDirecotory["/Users/xslittlegrass/"]

before calling the library function.

Question:

Is there other solutions, that can somehow tell the library function to search it's current directory? Because I will use the library function in parallel, and there may be many copies of library files in different locations, so I would prefer a more clean way to call the library function, instead of manually changing the path each time I call.

$\endgroup$
2
$\begingroup$

I think the simplest and platform-independent approach is to define a custom function which will temporarily set current working directory. I use the fact that the first argument of LibraryFunction is the full path to the library.

load = With[{f = #, dir = DirectoryName@#[[1]]}, 
      Module[{cwd = Directory[], res}, SetDirectory@dir; res = f@##; 
        SetDirectory@cwd; res] &] &@LibraryFunctionLoad@## &;

fun = load["demo", "demo_I_I", {Integer}, Integer]
Module[{cwd$ = Directory[], res$}, 
   SetDirectory["/usr/local/Wolfram/Mathematica/10.0/SystemFiles/Links/LibraryLink/\
     LibraryResources/Linux-x86-64/"]; 
   res$ = LibraryFunction["/usr/local/Wolfram/Mathematica/10.0/SystemFiles/Links/\
LibraryLink/LibraryResources/Linux-x86-64/demo.so", "demo_I_I", {
     Integer}, Integer][##1]; 
  SetDirectory[cwd$];
  res$] &

Another approach is to obtaining path of the library by the library itself, by it is more difficult: How do I get the directory that a program is running from?.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.