ayonga / frost-dev

Fast Robot Optimization and Simulation Toolkit (FROST)
http://ayonga.github.io/frost-dev/
Other
159 stars 64 forks source link

Mathlink dependency with deprecated MLDisownDoubleArray etc. #45

Closed joris997 closed 3 years ago

joris997 commented 3 years ago

Hello all. I'm trying to get frost-dev to work and am stuck on the dependencies. First of it seems that my Mathematica version came with libML64i4. files instead of i3.* files. I copied and renamed them which, when running testscript.m now seems to get past that issue.

Afterwards however I obtain the following error when running test-script:

>> testscript
Invalid MEX-file '/home/none/robotics/frost-dev/third/mathlink/math.mexa64': /home/none/robotics/frost-dev/third/mathlink/math.mexa64: undefined symbol: MLDisownDoubleArray

Error in testscript (line 1)
math('quit')

Which led me to think that some issue between i3. and i4. persists. If I look into mathlink.h (line 3634) indeed I see the notion that

/*
As of MLINTERFACE 3 the following functions have been deprecated.  Use the suggested functions in their
place:

MLDisownUnicodeString - MLReleaseUCS2String
MLDisownByteString    - MLReleaseByteString
MLDisownString        - MLReleaseString
*/

Subsequently I tried to compile the Mathlink code myself via the compileMatlink.m script that is included with the dependency (although it is mentioned that this would not be necessary) which results in the not completely unexpected error

Error using mex
/tmp/mex_93021259501672_31240/math.o: In function `WaitForReturnPacket':
math.c:(.text+0x124): undefined reference to `MLDisownString'
/tmp/mex_93021259501672_31240/math.o: In function `mexFunction':
math.c:(.text+0x9e4): undefined reference to `MLDisownString'
math.c:(.text+0xa98): undefined reference to `MLDisownDoubleArray'
collect2: error: ld returned 1 exit status

Error in compileMathlink (line 10)
mex(['-I', Mathematica_path, 'Links/MathLink/DeveloperKit/Linux-x86-64/CompilerAdditions/'], ...

So all seems related but I am not sure how to proceed with this. Anyone have any idea? Thanks in advance!

nr-codes commented 3 years ago

I am able to compile against the new MathLink v4 libraries in Windows 10 & Mathematica 12.2.0. I can post more specific steps later for what worked for me, but (similar to what you did) I basically made edits and recompiled math.c in ./third/mathlink/math.c (assuming you are in the frost top-level repo directory) using compileMathlink.m. The READMEs in the folder are helpful. Although I got things working, I don't know if these changes provide the same speed and functionality as the v3 library.

The changes I think you need to make are along the lines of replacing Disown with Release for the undefined references. Don't forget to locally copy the v4 .lib and .dll files into the same directory as the mex file.

I'm not sure if this would be helpful for linking against the v3 library or if there are simpler solutions (like fixing path assumptions made in the precompiled versions of mathlink).

nr-codes commented 3 years ago

So this was a two-step process for me (make sure to make backups of original files):

  1. Modify math.c by changing MLDisownString -> MLReleaseString and MLDisownDoubleArray -> MLReleaseDoubleArray. These changes are in 3 places in the file, I believe.
  2. Modify compileMathlink so that it compiles against the v4 library (see below)
function [] = compileMathlink()
% This is to compile mathlink to *.mex* files
% Note: the math.c has not been updated since 2004, thus there is no point
% for you to compile it yourself. 
% We recommend you to use the compiled *.mex* files included.

Mathematica_path = 'C:/Program Files/Wolfram Research/Mathematica/12.2/SystemFiles';
Link_path = 'Links/MathLink/DeveloperKit/Windows-x86-64/CompilerAdditions/';

compilerdir = fullfile(Mathematica_path, Link_path);
dlldir = fullfile(Mathematica_path, Link_path, '../', 'SystemAdditions');
headerdir =  fullfile(Mathematica_path, 'IncludeFiles/C');

fprintf('mex(\t\n%s, \t\n%s, \t\n%s, \t\n%s, \t\n%s, \t\n%s\n)\n\n',  ...
            '-D__STDC__', ...
            ['-I', compilerdir], ...
            ['-L', compilerdir], ...
            '-lml64i4', ...
            ['-I', headerdir], ...
            'math.c');

mex('-D__STDC__', ...
    ['-I', compilerdir], ...
    ['-L', compilerdir], ...
    '-lml64i4', ...
    ['-I', headerdir], ...
    'math.c');

out = fileparts(which('compileMathlink'));
copyfile(fullfile(compilerdir, 'ml64i4.lib'), out);
copyfile(fullfile(dlldir, 'ml64i4.dll'), out);

% Remove the ~ files if there are any.
delete('*.*~'); 

end

Hope this can be of use to people, but as a quick aside I am not associated with this project and will not be providing support for this code. The intent is for it to be used as a source of ideas to help you get around your particular issue.

The function above can easily be made more general by taking in some combination Mathematica's $InstallationDirectory, $Version, and $SystemID values as inputs, so that values such as 12.2 and Windows-x86-64 are not hard coded values.

joris997 commented 3 years ago

Thanks a lot nr-codes! My reply is a bit late but your second comment did the trick. Really appreciate the effort!