5
$\begingroup$

I have read calling-a-compiledfunction-dll-from-outside-mathematica and the CodeGeneration tutorial and scanned other related questions too numerous to mention, but I am still unclear about how to generate a DLL containing one or more compiled functions that I can call in Python.

The functions concerned take as parameters 1, 2 or 3D real valued arrays and various int/real scalars, and may also return arrays, multiple values (for assignment to multiple variables in Python).

(I also looked at pjlink @b3m2a1, but was concerned about overheads as the compiled functions will be heavily used, and then noticed it has been superseded by WolframClientForPython - I installed it anyway with pip but then noticed it says is requires Wolfram Language 11.3 or higher - alas I only have MMA 11.0.1 - is that an absolute pre-requisitive or recommendation? Update Looks absolute: evaluation generated error

WolframKernelException: Failed to communicate with kernel: C:\Program Files\Wolfram Research\Mathematica\11.0\WolframKernel.exe

)

Given that my C & compilation skills are negligible, and my ignorance of Windows executables, shells, etc. vast, can anyone provide or direct me to a minimum working example of: compiling >2 such functions into a DLL for the environment below?

The functions concerned do compile to C, do not call MainEvaluate and have been used successfully within MMA, I just need to re-use them in a Python environment.

Environment: MMA 11.0.1.0; Win 10 64-bit, VS Studio 2017, Python 3.6/7, Jupyterlab front-end.

Although useless on their own, here are examples of the compiled function definitions

pearsonRtoRefVector = Compile[{{dataVec, _Real,1}, {corrVecLen, _Integer},{corrVecMean, _Real}, {corrVecMeanDiffs, _Real, 1}, {corrVecMeanDiffsSquaredSummed, _Real}}, 
Module[
    {dataVecLen,dataVecMean, dataVecMeanDiffs,dataVecMeanDiffsSquaredSummed},
    dataVecLen = Length[dataVec];
    If[dataVecLen !=corrVecLen,
        -11, (* just a number that is not in the range[-1,1] *)
        dataVecMean = Last[Accumulate[dataVec]]/dataVecLen;
        dataVecMeanDiffs= dataVec - dataVecMean;
        dataVecMeanDiffsSquaredSummed = dataVecMeanDiffs.dataVecMeanDiffs;
        If[dataVecMeanDiffsSquaredSummed <= 2.2250738585072014`*^-308 (*$MinMachineNumber*), (* 2019-06-04 Why not just Chop, which is compilable *)
           0, (* clamp value to zero for effectively zero floats - can increase the size of "effectively zero" as required *)
           dataVecMeanDiffs.corrVecMeanDiffs/(Sqrt[dataVecMeanDiffsSquaredSummed]*Sqrt[corrVecMeanDiffsSquaredSummed])
        ]
    ]
], CompilationTarget -> "C", "RuntimeOptions" -> "Speed"];

(* COMPILATION TESTED OK 2017-02-12 Needed "InlineExternalDefinitions"\[Rule]True *)
(* It is assumed the following have been precomputed: the common correlation vector, vOscTable... 
   To see the effect of the Vosc table (which is assumed to have the right dimensions) pass a table filled with zeroes 
   Recall  that vOscTable has n columns and nc rows, i.e. indexes as [[nc, n]]*)
buildTAMSDTable = 
    Compile[{{aPQTable, _Real, 3},{gCorrVecLen, _Real}, {gCorrVecMean, _Real}, {gCorrVecMeanDiffs, _Real, 1}, {gCorrVecMeanDiffsSquaredSummed, _Real},{aVoscTable, _Real, 2}}, 
        Module[{pTable, qTable, ps, qs, pDiffs, qDiffs, bigN, intNcut,n,nc,cs,commonPQDims},
            pTable = aPQTable[[1]];
            qTable = aPQTable[[2]];
            commonPQDims = Dimensions[pTable];
            nc = commonPQDims[[1]]; (* #random c values = [[1]] because I am working on one of the translation variable sub-tables extracted *)
            bigN = Last[commonPQDims]; (* Number of points in data series *)
            intNcut = IntegerPart[bigN/10];

            Table[ (* Outer Table makes a vector of the correlations, but built-in Correlation is not compilable :( *)
                pearsonRtoRefVector[
                    Table[ (* This makes the mean squared deviations for correlation *) 
                        ps = pTable[[cs]]; (* Take one set of p values for the series *)
                        qs = qTable[[cs]]; (* Take one set of q values for the series *)
                        pDiffs = Take[ps, n - bigN] - Take[ps, bigN - n]; (* Calc the p diffs *)
                        qDiffs = Take[qs, n - bigN] - Take[qs, bigN - n]; (* Calc the q diffs *)
                        (1/(bigN - n) (pDiffs.pDiffs + qDiffs.qDiffs)) - aVoscTable[[cs, n]], (* The Mean of squared diffs summed - Vosc Continue to be wary of Vosc index order - ok but you never know!   *)
                        {n, 1, intNcut}], 
                    gCorrVecLen,gCorrVecMean,gCorrVecMeanDiffs,gCorrVecMeanDiffsSquaredSummed],
                {cs,1,nc}]
        ],
       CompilationTarget -> "C", "RuntimeOptions" -> "Speed", CompilationOptions->{"InlineCompiledFunctions"->True, "InlineExternalDefinitions"->True}];
$\endgroup$
  • $\begingroup$ A successful alternative approach using Wolfram Engine, Wolfram Client for Python and Mathematica source code compiling with Visual Studio 2017 is described in this answer: mathematica.stackexchange.com/a/210215/12858 $\endgroup$ – Julian Moore Nov 25 '19 at 20:31

Your Answer

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

Browse other questions tagged or ask your own question.