matlab mex clang C++11 thread -> Undefined symbols

2019-02-22 08:56发布

问题:

Goal: I want to use thread STL of C++11 in Matlab mex file (R2013a) using Xcode 4.6

I modified ~/.matlab/R2013a/mexopts.sh

        CC='clang++'   # was llvm-gcc-4.2
        CXX='clang++'   # was llvm-g++-4.2
        MACOSX_DEPLOYMENT_TARGET='10.8'   # was 10.5. C++11 is supported >=10.7
        CXXFLAGS="$CXXFLAGS -std=gnu++11 -stdlib=libc++"   # additional flags

Normal mex files without C++11 features are compiled well. Further, STL is well detected by the compiler except linking failure.

>> mex mextest.cpp

Undefined symbols for architecture x86_64:
"std::__1::__thread_struct::__thread_struct()", referenced from:                                      
    void* std::__1::__thread_proxy<std::__1::tuple<void (*)()> >(void*) in mextest.o                        
"std::__1::__thread_struct::~__thread_struct()", referenced from:                            
    void* std::__1::__thread_proxy<std::__1::tuple<void (*)()> >(void*) in mextest.o                        
"std::__1::__thread_local_data()", referenced from:                              
    void* std::__1::__thread_proxy<std::__1::tuple<void (*)()> >(void*) in mextest.o                      
"std::__1::__throw_system_error(int, char const*)", referenced from:                      
    _mexFunction in mextest.o                   
"std::__1::thread::join()", referenced from:                    
    _mexFunction in mextest.o                            
"std::__1::thread::~thread()", referenced from:                    
    _mexFunction in mextest.o    
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

    mex: link of ' "mextest.mexmaci64"' failed.

Error using mex (line 206)
Unable to complete successfully.

The actual source code is shown below. The details are not important because it compiles well in Matlab R2013 WINDOWS version with Visual Studio 2012 Express. An equivalent cpp was also well compiled with "clang++ -std=gnu++11 -stdlib=libc++ clangtest.cpp". So, at least, there is no logical error in the codes (I'm not saying it is safe codes. It is just a test.)

#include "mex.h"
#include <thread>
#include <stdio.h>

int count_thread1 = 0;
int count_thread2 = 0;

void hello()
{
    count_thread2 = 0;
    for(int i=0; i<=10000; i++){
        for (int j=1;j<=20000;j++){
            count_thread2 = i-j-1;
        }
        count_thread2++;
        printf("2: %d , %d\n", count_thread1, count_thread2); // Not sure if printf is thread-safe in Matlab. But it works in this particular example
    }
}
void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
{
    count_thread1 = 0;
    std::thread t(hello);
    for (int i=1;i<=10000;i++)
    {
        for (int j=1;j<=20000;j++){
            count_thread1 = -i+j-1;
        }
        count_thread1++;
        mexPrintf("1: %d , %d\n", count_thread1, count_thread2);
    }
    mexPrintf("\n");
    t.join();
    mexPrintf("Done\n");
}

It seems like I have to replace some include directories and/or library directories. What kind of options should be modify?

Thank you.

回答1:

The error is due to compiling against -stdlib=libc++ but linking against -lstdc++. You can fix it in one of two ways:

  1. Fix it in mexopts.sh. The most drastic and effective solution. Located in ~/.matlab/${MATLAB_VERSION}/mexopts.sh, this determines all compiler options. Simply find/replace all stdc++ to c++.

  2. Patchwork solution: Simply add -lc++ to the tail end of CXXLIBS. I'm not sure what the effect of linking against multiple versions of the standard libraries is, but it seems to work. In your mex invocation, add the argument CXXLIBS="\$CXXLIBS -lc++".

As a secondary issue, I believe you're completely overwriting the value of CXXFLAGS; you must escape the $ symbol as I did above with the libraries.