Когда вы видите ошибку, ссылающуюся на что-то вроде _ZN6SeqLib14FermiAssemblerD1Ev
, первый шаг, чтобы запустить его через имя demangler как c++filt
, которые должны быть включены в любом дистрибутиве Linux:
$ c++filt _ZN6SeqLib14FermiAssemblerD1Ev
# SeqLib::FermiAssembler::~FermiAssembler()
Проблема заключается в том, что в файле заголовка вы имеете объявили деструктор для класса FermiAssembler
, но не указали определение для этого. Ваши варианты:
- Удалите декларацию целиком. Если деструктор для этого класса не делает ничего особенного, например освобождение динамически выделенной памяти или данных регистрации, и т. Д., Вы должны быть в порядке с деструктором по умолчанию, сгенерированным компилятором. Однако, если вы предоставляете декларацию, такую как вы делали выше, вы сообщаете компилятору «деструктор для этого класса должен сделать что-то дополнительное, поэтому не создавайте его для меня».
- Обеспечить пустое определение:
~FermiAssembler() {}
(обратите внимание на фигурные скобки, которые отличают это от декларации). Это эквивалентно использованию созданного компилятором деструктора, как описано выше.
- Предоставить непустое определение . В этом простом примере класс
FermiAssembler
не нуждается в деструкторе не по умолчанию, но в целях демонстрации мы рассмотрим этот вариант ниже.
Вот файл макета я буду использовать; вам нужно будет настроить пути #include
и т. д.соответственно:
tree example/
# example/
# ├── DESCRIPTION
# ├── example.Rproj
# ├── NAMESPACE
# ├── R
# │ └── RcppExports.R
# └── src
# ├── demo.cpp
# ├── FermiAssembler.cpp
# ├── FermiAssembler.h
# └── RcppExports.cpp
Заголовок FermiAssembler.h
теперь становится:
#ifndef SEQLIB_FERMI_H
#define SEQLIB_FERMI_H
namespace SeqLib {
class BamRecordVector;
void print_my_name();
class FermiAssembler {
public:
FermiAssembler();
~FermiAssembler();
void AddReads(const BamRecordVector& brv);
};
} // SeqLib
#endif // SEQLIB_FERMI_H
Обратите внимание, что я также конвертируются print_my_name
в прототипе функции, поэтому она будет также должны быть определены в соответствующем исходном файле , Кроме того, вы можете переместить предыдущие #include
S к исходному файлу, так как они больше не нужны здесь:
// FermiAssembler.cpp
#include "FermiAssembler.h"
#include <iostream>
#include <Rcpp.h>
namespace SeqLib {
void print_my_name() {
std::cout << "It's Crt";
}
FermiAssembler::FermiAssembler()
{
Rcpp::Rcout << "FermiAssembler constructor\n";
}
FermiAssembler::~FermiAssembler()
{
Rcpp::Rcout << "FermiAssembler destructor\n";
}
} // SeqLib
Наконец, файл, чтобы использовать этот класс:
// demo.cpp
#include "FermiAssembler.h"
// [[Rcpp::export]]
int whats_my_name() {
SeqLib::FermiAssembler f;
return 0;
}
После строительства и установки упаковки оно работает как ожидалось:
library(example)
whats_my_name()
# FermiAssembler constructor
# FermiAssembler destructor
# [1] 0
Update Что касается вашего вопроса о «Может быть исходные файлы в других местах, чем верхний уровень src/
каталогов?», да, вы можете, но я бы советовал это, так как для этого потребуется нетривиальный файл Makevars
. Теперь, используя эту схему,
tree example
# example
# ├── DESCRIPTION
# ├── example.Rproj
# ├── man
# ├── NAMESPACE
# ├── R
# │ └── RcppExports.R
# ├── SeqLib
# │ ├── SeqLib
# │ │ └── FermiAssembler.h
# │ └── src
# │ └── FermiAssembler.cpp
# └── src
# ├── demo.cpp
# ├── Makevars
# └── RcppExports.cpp
мы имеем в каталоге верхнего уровня src/
(неSeqLib/src
) это Makevars
:
PKG_CXXFLAGS= -I../SeqLib
SOURCES = $(wildcard ../SeqLib/*/*.cpp *.cpp)
OBJECTS = $(wildcard ../SeqLib/*/*.o *.o) $(SOURCES:.cpp=.o)
Обратите внимание, что в приведенном выше примере мы просто компиляции всех объектных файлов в одна и та же разделяемая библиотека. Если вам нужно, например, скомпилировать промежуточные общие или статические библиотеки и связать их с окончательным .so
, тогда ожидайте, что ваш Makevars
получит много грязнее.
Восстановление и установка,
library(example)
whats_my_name()
# FermiAssembler constructor
# FermiAssembler destructor
# [1] 0
Спасибо за глубины ответ! Я фактически определил деструктор в отдельном файле, см. Отредактированный ответ. – Crt
Я не понимаю вашего комментария. – nrussell
Я отредактировал исходный вопрос, чтобы включить ** определение ** деструктора. – Crt