2016-11-01 2 views
0

Я могу ссылаться на функции из пространства имен, но не классов. Вот файл имен SeqLib/FermiAssembler.h»Способность к ссылочным функциям Но, не классы в пространстве имен

#ifndef SEQLIB_FERMI_H 
#define SEQLIB_FERMI_H 

#include <string> 
#include <cstdlib> 
#include <iostream> 

namespace SeqLib 
{ 

    void print_my_name(){ std::cout << "It's Crt" } 
    class FermiAssembler { 
    public: 
     FermiAssembler(); 

     ~FermiAssembler(); 

     void AddReads(const BamRecordVector& brv); 
    }; 
} 

Я могу назвать print_my_name() via SeqLib::print_my_name(), но не в состоянии ссылаться на класс FermiAssembler через SeqLib::FermiAssembler f

Вот файл C++ в моей /src

#include <iostream> 
#include <Rcpp.h> 
#include "SeqLib/FermiAssembler.h" 
using namespace std; 

// [[Rcpp::export]] 
void whats_my_name(){ 
    SeqLib::FermiAssembler f; 

Вот структура пакета

temp 
    seqLib 
    SeqLib 
    src 
     FermiAssembler.cpp 
    SeqLib 
     FermiAssembler.h 
    headerFiles 
    SeqLibCommon.h 
    src 
    hello_world.cpp 
    Makevars which contains PKG_CXXFLAGS= -I../SeqLib 

Вот FermiAssembler.cpp определяется

#include "SeqLib/FermiAssembler.h" 
#define MAG_MIN_NSR_COEF .1 

namespace SeqLib { 
    FermiAssembler::~FermiAssembler() { 
     ClearReads(); 
     ClearContigs(); 
    } 
} 

Сообщение об ошибке: Error in dyn.load(dllfile) :
unable to load shared object 'temp/seqLib/src/SeqLib.so':
temp/seqLib/src/SeqLib.so: undefined symbol: _ZN6SeqLib14FermiAssemblerD1Ev

обновление Я переместил весь подмодуль в папку Src, как например:

# temp 
# |─── src 
#  |────SeqLib 
#    |──────SeqLib 
#      |────── FermiAssembler.h 
#    |──────src 
#      |────── FermiAssembler.cpp 

ответ

3

Когда вы видите ошибку, ссылающуюся на что-то вроде _ZN6SeqLib14FermiAssemblerD1Ev, первый шаг, чтобы запустить его через имя demangler как c++filt, которые должны быть включены в любом дистрибутиве Linux:

$ c++filt _ZN6SeqLib14FermiAssemblerD1Ev 
# SeqLib::FermiAssembler::~FermiAssembler() 

Проблема заключается в том, что в файле заголовка вы имеете объявили деструктор для класса FermiAssembler, но не указали определение для этого. Ваши варианты:

  1. Удалите декларацию целиком. Если деструктор для этого класса не делает ничего особенного, например освобождение динамически выделенной памяти или данных регистрации, и т. Д., Вы должны быть в порядке с деструктором по умолчанию, сгенерированным компилятором. Однако, если вы предоставляете декларацию, такую ​​как вы делали выше, вы сообщаете компилятору «деструктор для этого класса должен сделать что-то дополнительное, поэтому не создавайте его для меня».
  2. Обеспечить пустое определение: ~FermiAssembler() {} (обратите внимание на фигурные скобки, которые отличают это от декларации). Это эквивалентно использованию созданного компилятором деструктора, как описано выше.
  3. Предоставить непустое определение . В этом простом примере класс 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 

+0

Спасибо за глубины ответ! Я фактически определил деструктор в отдельном файле, см. Отредактированный ответ. – Crt

+0

Я не понимаю вашего комментария. – nrussell

+0

Я отредактировал исходный вопрос, чтобы включить ** определение ** деструктора. – Crt

Смежные вопросы