Связывание ошибок из библиотеки MATLAB Mex

У меня проблемы с компиляцией библиотеки 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

Еще несколько подробностей о моей машине:

  • OSX 10.6.8
  • MATLAB R2012a (также есть R2011b)
  • g ++ 4.2 или g ++ 4.0 (или g ++ 4.6 через MacPorts)

Я добавил некоторые детали того, чего я действительно хочу, из ответа в моем «описании награды» ниже.

РЕДАКТИРОВАТЬ 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";
}

3

Решение

Кажется, проблема в том, что некоторый код шаблона находится в файлах .cpp.

  1. Удалить #include instances.inc декларации от .cpp файлы.
  2. Переместить весь код из QPBO.cpp, QPBO_extra.cpp, QPBO_maxflow.cpp а также QPBO_postprocessing.cpp в заголовочный файл qpbo.h.
  3. Теперь у вас будет один файл .cpp qpbo_wrapper_mex.cpp и один заголовок qpbo.h
  4. MEX файл (в Matlab), используя:

    >> mex -O -largeArrayDims qpbo_wrapper_mex.cpp
    

Должно сработать…

5

Другие решения

изменения GetMaxEdgeNum к статической функции или помещению ее в анонимное пространство имен, вероятно, решит вашу проблему.

Причина, как вы предполагаете, заключается в том, что он имеет внешнюю связь в обоих объектных файлах, что приводит к конфликту имен. Мои предложенные решения дают ему внутреннюю связь.

После редактирования:

Изменится ли что-нибудь, если вы определите метод внутри определения класса?
Как это:

template <typename REAL>
class QPB0 {
...
public:
inline int GetMaxEdgeNum()
{
return (int)(arc_max[0]-arcs[0])/2;
}
...
};
3

По вопросам рекламы [email protected]