I've been thinking about adding direct external references as an alternative to dynamic loading of libraries. The mechanism is all there now because the Poly/ML run-time library is linked to the exported code through external references.
I've added Foreign.externalFunctionSymbol : string -> symbol This creates an external reference which is filled in when the code is exported. The actual value is resolved by linking with the appropriate library. For your example that means changing it to replace references to getSymbol to externalFunctionSymbol and removing the calls to loadLibrary. i.e. open Foreign;
type gsl_matrix_t = Memory.voidStar; (* for demonstration only *) local val call1 = buildCall2((externalFunctionSymbol "gsl_matrix_calloc"), (cInt,cInt), cPointer) val call2 = buildCall4((externalFunctionSymbol "gsl_matrix_set"), (cPointer,cInt,cInt,cDouble), cVoid) val call3 = buildCall3((externalFunctionSymbol "gsl_linalg_exponential_ss"), (cPointer, cPointer, cDouble), cVoid) in fun gsl_matrix_alloc (size1,size2) = call1(size1,size2)
It seems to handle your example fine when the code is exported using "polyc" and then linked with the libraries.
I've committed this to a separate branch "ExternalBranch" on GitHub rather than "master". I'd like some feedback on how useful this is and whether there are any problems before merging it.
David
On 09/09/2018 21:15, Mark Clements wrote:
I am enjoying using polyml's Foreign structure.
However, in using the GNU Scientific Library (GSL), I have run into a problem with linkage. The GSL library (libgsl.so) calls standard cBLAS matrix functions with unknown symbols to allow the user to link with different cBLAS implementations (NB: GSL provides an unoptimised cBLAS implementation named libgslcblas.so). When I call a GSL function that depends on the cBLAS functions, I get a symbol not defined error.
I have tried unsuccessfully (a) loading the libgslcblas library either before or after loading libgsl, (b) changing the loadLibrary implementation to use dlopen with RTLD_LAZY | RTLD_GLOBAL, and (c) compiling the SML code to an object file and then linking against the libraries.
How could this be made to work?
Sincerely, Mark.
PS test code for (a) is:
open Foreign; val gsl = loadLibrary "/usr/lib/x86_64-linux-gnu/libgsl.so"; val gslcblas = loadLibrary "/usr/lib/x86_64-linux-gnu/libgslcblas.so"; type gsl_matrix_t = Memory.voidStar; (* for demonstration only *) local val call1 = buildCall2((getSymbol gsl "gsl_matrix_calloc"), (cInt,cInt), cPointer) val call2 = buildCall4((getSymbol gsl "gsl_matrix_set"), (cPointer,cInt,cInt,cDouble), cVoid) val call3 = buildCall3((getSymbol gsl "gsl_linalg_exponential_ss"), (cPointer, cPointer, cDouble), cVoid) in fun gsl_matrix_alloc (size1,size2) = call1(size1,size2) fun gsl_matrix_set (ptr : gsl_matrix_t, i, j, x) = call2(ptr, i, j, x) fun gsl_matrix (arr : real Array2.array) = let val size1 = Array2.nRows arr val size2 = Array2.nCols arr val ptr = gsl_matrix_alloc(size1, size2) val _ = Array2.tabulate Array2.RowMajor (size1, size2, fn (i,j) => gsl_matrix_set(ptr, i, j, Array2.sub(arr, i, j))) in ptr end fun gsl_mexp (arr : real Array2.array) = let val size1 = Array2.nRows arr val size2 = Array2.nCols arr val ptr = gsl_matrix arr val ptr2 = gsl_matrix_alloc(size1, size2) val _ = call3(ptr, ptr2, 0.01) in ptr2 end end; fun main() = let val a = Array2.fromList [[1.0,2.0],[3.0,4.0]]; val ptr = gsl_matrix(a); val m = gsl_mexp(a) (* fails *) in () end; (* symbol lookup error: /usr/lib/x86_64-linux-gnu/libgsl.so: undefined symbol: cblas_dgemm *)
For (c):
polyc -c test.sml g++ test.o -L/usr/lib/x86_64-linux-gnu -lgsl -lgslcblas `pkg-config --libs polyml` ./a.out # same error _______________________________________________ polyml mailing list polyml at inf.ed.ac.uk http://lists.inf.ed.ac.uk/mailman/listinfo/polyml