У меня проблемы с компиляцией библиотеки MATLAB Mex, в частности кода «Оптимизация корреляционной кластеризации» из этот сайт.
Я пытаюсь скомпилировать на компьютере с OSX и использую прилагаемый mexall
функция. Это запускает следующую строку:
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
Ошибка возникает при связывании следующего вывода с командной строкой MATLAB:
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.
Судя по этому, функция GetMaxEdgeNum
появляется в обоих QPBO_extra.o
а также QPBO.o
, Тем не менее, это только на самом деле определяется в заголовочном файле, QPBO.h
, Поэтому я подозреваю, что оба исходных файла, которые включают его, включают его в качестве символа в свои объектные файлы, вызывая проблему во время ссылки.
(Дополнительная информация: каждый исходный файл также включает в себя файл #include "instances.inc"
на самом конец файла. instances.inc
по-видимому, включает в себя некоторые конкретные экземпляры шаблонного QPBO
.)
Есть ли очевидная ошибка, которую я делаю здесь? Что я могу сделать, чтобы увеличить мои шансы на возможность компилировать этот код?
РЕДАКТИРОВАТЬ
Это определение проблемного GetMaxEdgeNum
функция в QPBO.h
:
template <typename REAL>
inline int QPBO<REAL>::GetMaxEdgeNum()
{
return (int)(arc_max[0]-arcs[0])/2;
}
РЕДАКТИРОВАТЬ 2
Еще несколько подробностей о моей машине:
Я добавил некоторые детали того, чего я действительно хочу, из ответа в моем «описании награды» ниже.
РЕДАКТИРОВАТЬ 3
Есть немного консенсуса, что instances.inc
может быть причиной проблемы. Это включено в конце каждого cpp
файл, и он содержит следующее:
#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";
}
Кажется, проблема в том, что некоторый код шаблона находится в файлах .cpp.
#include instances.inc
декларации от .cpp
файлы.MEX файл (в Matlab), используя:
>> mex -O -largeArrayDims qpbo_wrapper_mex.cpp
Должно сработать…
изменения GetMaxEdgeNum
к статической функции или помещению ее в анонимное пространство имен, вероятно, решит вашу проблему.
Причина, как вы предполагаете, заключается в том, что он имеет внешнюю связь в обоих объектных файлах, что приводит к конфликту имен. Мои предложенные решения дают ему внутреннюю связь.
После редактирования:
Изменится ли что-нибудь, если вы определите метод внутри определения класса?
Как это:
template <typename REAL>
class QPB0 {
...
public:
inline int GetMaxEdgeNum()
{
return (int)(arc_max[0]-arcs[0])/2;
}
...
};