I am having troubling compiling a MATLAB Mex library - specifically, the 'Correlation Clustering Optimization' code from this website.
I am trying to compile on an OSX machine, and am using the supplied mexall function. This runs the following line:
mex -O -largeArrayDims CXXFLAGS="\$CXXFLAGS -Wno-write-strings" QPBO.cpp QPBO_extra.cpp QPBO_maxflow.cpp QPBO_wrapper_mex.cpp QPBO_postprocessing.cpp -output QPBO_wrapper_mex
The error occurs at linking time with the following output to the MATLAB command line:
ld: duplicate symbol QPBO<int>::GetMaxEdgeNum() in QPBO_extra.o and QPBO.o
collect2: ld returned 1 exit status
mex: link of ' "QPBO_wrapper_mex.mexmaci64"' failed.
Judging from this, the function GetMaxEdgeNum is appearing in both QPBO_extra.o and QPBO.o. However, it is only actually defined in a header file, QPBO.h. I therefore suspect that both source files which include it are including it as a symbol in their object files, causing a problem at link time.
(Further information: Each source file also includes a file #include "instances.inc" at the very end of the file. instances.inc apparently seems to include some specific instantiations of the templated QPBO.)
Is there an obvious mistake I am making here? What can I do to increase my chances of being able to compile this code?
EDIT
This is the definition of the problematic GetMaxEdgeNum function in QPBO.h:
template <typename REAL>
inline int QPBO<REAL>::GetMaxEdgeNum()
{
return (int)(arc_max[0]-arcs[0])/2;
}
EDIT 2
Some more details about my machine:
I've added some details on what I really want from an answer in my 'bounty description' below.
EDIT 3
There's a bit of consensus that instances.inc may be causing the trouble. This is included at the end of each cpp file, and it contains the following:
#include "QPBO.h"
#ifdef _MSC_VER
#pragma warning(disable: 4661)
#endif
// Instantiations
template class QPBO<int>;
template class QPBO<float>;
template class QPBO<double>;
template <>
inline void QPBO<int>::get_type_information(char*& type_name, char*& type_format)
{
type_name = "int";
type_format = "d";
}
template <>
inline void QPBO<float>::get_type_information(char*& type_name, char*& type_format)
{
type_name = "float";
type_format = "f";
}
template <>
inline void QPBO<double>::get_type_information(char*& type_name, char*& type_format)
{
type_name = "double";
type_format = "Lf";
}
It seems like the issue is that some template code is in .cpp files.
#include instances.inc declarations from the .cpp files.mex the file (in matlab) using:
>> mex -O -largeArrayDims qpbo_wrapper_mex.cpp
Should work...
Changing GetMaxEdgeNum to a static function, or putting it in an anonymous namespace will probably fix your problem.
The reason is, as you suggest, that it has external linkage in both object files, which results in a nameclash. My suggested solutions gives it internal linkage.
After edit:
Does it change anything if you define the method inside the class definition? Like this:
template <typename REAL>
class QPB0 {
...
public:
inline int GetMaxEdgeNum()
{
return (int)(arc_max[0]-arcs[0])/2;
}
...
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With