New C++ Interface with Shared Library not working (R2019a)

Hello,
I have been testing the automatically generated C++ interface but ran into few problems (split into separate questions) (other question How to unload library?).
In general, I can generate and use an interface when the "header only" version is used. But as soon as I include a library (*.so) (which I think is kind of the point), the interface does not work.
I can define the interface (via clibgen.generateLibraryDefinition) and build the interface ( via e.g. build(definemyPkg)) without errors but I cannot use it (e.g. via clib.myPkg.Mat -> Undefined variable "clib" or class "clib.myPkg.Mat").
First, I tested with some basic self written test classes/files/libs, toyed around with the "auto.h" example from the blog post and after this didn't work, I tested with the example given in the docu adapted to our Linux system (see script below) (BTW, wondering why is there no Linux example?) (Define and Publish Interface to C++ Shared Library).
I admit, I am not a C++ expert or have a lot of experience with shared libraries, so if I have overseen something profoundly, please let me know.
Any help or ideas are appreciated. If you need more info or want to see the code for the other tests, let me know.
Cheers
Henning
UPDATE from Accepted Answer:
The environment variable LD_LIBRARY_PATH must be set to include the shared library file before starting MATLAB (for me, did not work when setting in MATLAB directly).
See docu (which I overlooked) System Requirements
I added a new test script.
tested on Centos7, R2019a (and quickly on RHEL8 with pre-release R2019b, which we are of course not allowed to talk about :))
Tested with compilers: gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36) and gcc (GCC) 6.3.1 20170216 (Red Hat 6.3.1-3)
This is the test script:
% adapted from
% https://de.mathworks.com/help/matlab/matlab_external/define-and-publish-matlab-interface-for-shared-library.html
% working directory is /dir/to/TestCppInterface/
%%
FolderWorking = "/dir/to/TestCppInterface/";
FolderLib = "/dir/to/TestCppInterface/linux64/gcc/";
cd(FolderWorking)
%%
copyfile(fullfile(matlabroot,'extern','examples','cpp_interface','matrixOperations.*'),'.','f')
copyfile(fullfile(matlabroot,'extern','examples','cpp_interface','cppshrhelp.hpp'),'.','f')
%%
if ~isdir('linux64')
mkdir('linux64')
if ~isdir(fullfile('linux64','gcc'))
mkdir(fullfile('linux64','gcc'))
end
end
%%
% linux
copyfile( fullfile(matlabroot,'extern','examples','cpp_interface','glnxa64','*.*'),...
fullfile('linux64','gcc'),'f')
%%
% path = getenv('path'); % windows example with lower case
path = getenv('PATH');
%%
setenv('PATH', [ char(FolderWorking) ':' char(FolderLib) ':' path]);
%%
% Full path to files in the library
% productPath = 'H:\Documents\MATLAB\publisher\matrixexample';
productPath = char(FolderWorking);
% Header file name
hppFile = 'matrixOperations.hpp';
% Full path to folder containing all header files
hppPath = productPath;
% Full path to folder containing include files
iPath = hppPath;
% Full path to folder containing library files. This example uses the MinGW-w64 compiler.
% libPath = fullfile(productPath,'win64','mingw64');
libPath = fullfile(productPath,'linux64','gcc');
% Library file name
% libFile = 'matrixOperations.lib';
libFile = 'libmwmatrixOperations.so';
%%
myPkg = 'myPkg';
%%
v = true;
clibgen.generateLibraryDefinition(fullfile(hppPath,hppFile),...
'IncludePath', iPath,...
'Libraries', fullfile(libPath,libFile),...
'PackageName', myPkg,...
'Verbose',v)
%%
% complete the missing definitions as required (or just build with missing
% methods)
%%
build(definemyPkg)
%%
addpath('./myPkg')
%%
matObj = clib.myPkg.Mat; % not working
% Undefined variable "clib" or class "clib.myPkg.Mat"
New, adapted script:
%%
%
%
%
% adapted from
% https://de.mathworks.com/help/matlab/matlab_external/define-and-publish-matlab-interface-for-shared-library.html
%
% see also answer on MathWorks forum
% https://de.mathworks.com/matlabcentral/answers/472129-new-c-interface-with-shared-library-not-working-r2019a
% working directory is /dir/to/TestCppInterface/
%%
% IMPORTANT NOTE
% On Linux, make sure the environment variable `LD_LIBRARY_PATH` includes
% the path to the lib that is to be used BEFORE starting MATLAB.
% For example, for this example script
% ~~~
% setenv LD_LIBRARY_PATH $LD_LIBRARY_PATH:/dir/to/TestCppInterface/linux64/gcc
% echo $LD_LIBRARY_PATH
% matlab
% ~~~
%%
FolderWorking = "/dir/to/TestCppInterface/";
cd(FolderWorking)
%%
copyfile(fullfile(matlabroot,'extern','examples','cpp_interface','matrixOperations.*'),'.','f')
copyfile(fullfile(matlabroot,'extern','examples','cpp_interface','cppshrhelp.hpp'),'.','f')
%%
if ~isdir('linux64')
mkdir('linux64')
if ~isdir(fullfile('linux64','gcc'))
mkdir(fullfile('linux64','gcc'))
end
end
%%
% linux
copyfile( fullfile(matlabroot,'extern','examples','cpp_interface','glnxa64','*.*'),...
fullfile('linux64','gcc'),'f')
%%
% just to check that the path to the lib is included
TmpLDPath = getenv("LD_LIBRARY_PATH")
%%
% Full path to files in the library
% productPath = 'H:\Documents\MATLAB\publisher\matrixexample';
productPath = char(FolderWorking);
% Header file name
hppFile = 'matrixOperations.hpp';
% Full path to folder containing all header files
hppPath = productPath;
% Full path to folder containing include files
iPath = hppPath;
% Full path to folder containing library files. This example uses the MinGW-w64 compiler.
% libPath = fullfile(productPath,'win64','mingw64');
libPath = fullfile(productPath,'linux64','gcc');
% Library file name
% libFile = 'matrixOperations.lib';
libFile = 'libmwmatrixOperations.so';
%%
myPkg = 'myPkg';
%%
v = true;
clibgen.generateLibraryDefinition(fullfile(hppPath,hppFile),...
'IncludePath', iPath,...
'Libraries', fullfile(libPath,libFile),...
'PackageName', myPkg,...
'Verbose',v)
%%
% complete the missing definitions as required (or just build with missing
% methods)
%%
build(definemyPkg)
%%
addpath('./myPkg')
%%
matObj = clib.myPkg.Mat;

 Accepted Answer

Hi Henning,
Thanks for trying this out! I think you need to set the LD_LIBRARY_PATH (on Windows, we set PATH) so that the system can find the '.so' you want to call.
setenv LD_LIBRARY_PATH $LD_LIBRARY_PATH:/<your_so_path>
For example
setenv LD_LIBRARY_PATH $LD_LIBRARY_PATH:/usr/local/lib
Please note that if you have any dependencies that the main library needs, then they also need to be added to the LD_LIBRRAY_PATH. Hope that resolves the issue.
Vivek

6 Comments

Hi Vivek,
this did help! Thanks a lot!
When I set the LD_LIBRARY_PATH to include the path of the lib (e.g. in this case the path in which libmwmatrixOperations.so is placed) before MATLAB is started, everything works.
See docu (which I overlooked) System Requirements
(Interestingly, after a few tests, it does not work if I set the LD_LIBRARY_PATH in MATLAB directly. The variable must be set before starting MATLAB (sorry if this is trivial, but I do not have a lot of experience with shared libraries).
Is this supposed to be like this?)
As a suggestion, please add an example for Linux to the docu of this interface (similar to the Windows example).
Thanks again for your help!
Henning
Hi Henning,
What you've observed about LD_LIBRARY_PATH is consistent with expected behavior on Linux (sorry I didn't make this explicit in my previous response). In fact it's always a good idea to set the environment variable before MATLAB is started. That ensures that the library is always available.
Thanks for your feedback on the documentation, we are working on an example for Linux.
Vivek
Hi Everyone. I am having the same issue of being unable to use the MATLAB generated interface library (.dll) file. I followed the matrix example provided by MATLAB as seen here. I am able to successfully build the interface dll. I make sure to add the directory containing that dll to the MATLAB path but I am unable to use any functions from the C++ library. MATLAB complains about being unable to resolve the names (clib.myPkg.Mat). I am working on a Windows computer. Is there an analagous solution to the one above for windows?
To answer my own question, the equivalent process is to set the system path environment variables to contain the directories for all library files required (the MATLAB interface dll and any others) prior to starting MATLAB as this link indicates: https://www.mathworks.com/help/matlab/matlab_external/call-functions-in-interface-to-matrixoperations-library.html. Now I have the MATLAB matrix example working. This thread was very useful. Thanks everyone.
> Thanks for your feedback on the documentation, we are working on an example for Linux. (19 Jul 2019)
I need to use a set of C/C++ interfaces (defined in header and implemented in a shared library which depends on other linux pkgs - e.g. Eigen::Vector and Matrix). I would like to try this framework (instead of mexFunction). Please let me know if the working example for Linux is available.

Sign in to comment.

More Answers (0)

Asked:

on 17 Jul 2019

Commented:

on 21 Apr 2020

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!