Символ (ы) не найден для архитектуры i386, несмотря на компиляцию универсальной и i386 версий библиотеки

Я занимаюсь разработкой динамической библиотеки на C ++, которая компилируется и запускается при тестировании в проекте интерфейса командной строки xcode и в проекте gtest.

Однако, когда я пытаюсь связать его в проекте openframeworks, компоновщик жалуется на невозможность найти символы i386 для некоторых функций одного из моих классов. Это особенно странно, так как он может видеть символы для 16 из 21 функций, конструкторов & деструктор … Я знаю это, потому что я могу позвонить всем 16 без проблем с компоновщиком и получить ожидаемые результаты.

Вот что выплевывает Xcode:

Undefined symbols for architecture i386:
"Cicada::Message::load(std::string const&)", referenced from:
ofApp::setup() in ofApp.o
"Cicada::Message::save(std::string const&)", referenced from:
ofApp::setup() in ofApp.o
"Cicada::Message::setContent(std::string)", referenced from:
ofApp::setup() in ofApp.o
"Cicada::Message::parse(std::string, bool)", referenced from:
ofApp::setup() in ofApp.o
"Cicada::Message::Message(std::string, Cicada::CALL_TO_ACTION, bool)", referenced from:
ofApp::setup() in ofApp.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

В качестве проверки работоспособности я позвонил в библиотеку «липо»:

> lipo -info bin/libcicada.0.0.1.dylib
> Architectures in the fat file: bin/libcicada.0.0.1.dylib are: x86_64 i386

Затем я позвонил в nm, чтобы узнать, смогу ли я «найти» символы, с которыми он боролся:

> nm -gj -arch i386 bin/libcicada.0.0.1.dylib
...
__ZN6Cicada7Message10setContentENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE
__ZN6Cicada7Message11generateUIDEv
__ZN6Cicada7Message13header_lengthE
__ZN6Cicada7Message13hexifyContentEv
__ZN6Cicada7Message14generateHeaderEv
__ZN6Cicada7Message15dehexifyContentEv
__ZN6Cicada7Message4loadERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE
__ZN6Cicada7Message4saveERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE
__ZN6Cicada7Message5parseENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEb
__ZN6Cicada7Message5printEv
__ZN6Cicada7Message6setCTAENS_14CALL_TO_ACTIONE
__ZN6Cicada7Message8toStringEv
__ZN6Cicada7MessageC1ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS_14CALL_TO_ACTIONEb
__ZN6Cicada7MessageC1Ev
__ZN6Cicada7MessageC2ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS_14CALL_TO_ACTIONEb
__ZN6Cicada7MessageC2Ev
__ZN6Cicada7MessageD0Ev
__ZN6Cicada7MessageD1Ev
__ZN6Cicada7MessageD2Ev
...

Символы, которые компоновщик не видит:

__ZN6Cicada7Message10setContentENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE
__ZN6Cicada7Message4loadERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE
__ZN6Cicada7Message4saveERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE
__ZN6Cicada7Message5parseENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEb
__ZN6Cicada7MessageC1ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS_14CALL_TO_ACTIONEb

главный конструктор setContent, parse, save и load.

Я знаю, что 64-битная функциональность появилась на openframeworks только в версии 9, отсюда и компиляция для универсального бинарного файла. Я даже пытался компилировать исключительно для i386, но не играли в кости …

Я пробовал различные архитектуры и SDK для проекта openframeworks, но что-либо, кроме $ (NATIVE_ARCH) по умолчанию, мешает компиляции самого openframeworks. Путь поиска в библиотеке указывает на правильные местоположения, и я ссылаюсь на правильную библиотеку на этапах сборки, что очевидно благодаря тому, что она успешно компилируется и запускается, когда закомментированы вызовы вызывающих функций.

У меня есть ноющее чувство, что это проблема C ++ 11, так как она используется во всей моей библиотеке, и если моя память мне правильно служит, у openframeworks есть проблемы с C ++ 11. Если кто-то думает, что это может быть что-то еще, я был бы признателен за вклад !!!

Вот копия проблемного класса …

//
//  Message.h
//  Cicada
//
//  Created by Pierre Chanquion on 06/09/2014.
//

#include "Definitions.h"#include "Serialisable.h"
// ••••••••••••••••••••••••••••••••••••••••••••••••••••••
// • Message: Class for  parsing, loading, saving
// ••••••••••••••••••••••••••••••••••••••••••••••••••••••
namespace Cicada {
class Message : public Serialisable {
private:
// ----------------------------------------------->
// content : Data (i.e. the message)
// header  : Header
// cta     : Call to Action
// ishex   : Flag denoting content format
std::string content, header;
static const size_t header_length;
size_t uid;
CTA    cta;
bool   ishex;
ECL    ecl;
// ----------------------------------------------->
// Generates a header string
void generateHeader();

// ----------------------------------------------->
// Generates a header string
void generateUID();

public:
// ----------------------------------------------->
// Constructors
//  @con : content
//  @cta : cta
Message(std::string con, CTA cta, bool ishex = false);
Message();

// ----------------------------------------------->
// Destructor
~Message();

// ----------------------------------------------->
// Print message
void print();

// ----------------------------------------------->
// Stringify message
std::string toString();

// ----------------------------------------------->
// Parse message
//  @m   : stringified message to parse
//  @hex : flag denoting payload format
RC parse(std::string m, bool hex);

// ----------------------------------------------->
// Serialisation functions
//  @fp : filepath
virtual RC save(const std::string &fp);
virtual RC load(const std::string &fp);

// ----------------------------------------------->
// Conversions between char and ascii no
// representations
void hexifyContent();
void dehexifyContent();

// ----------------------------------------------->
// Accessors
void setContent(std::string con);
void setCTA(CTA cta);
void setECL(ECL ecl) { this->ecl = ecl;}

inline void setHex(bool b){ ishex = b;}
inline std::string getContent() { return content; }
inline std::string getHeader() { return header; }
inline CTA    getCTA() { return cta; }
inline size_t getUID() { return uid; }
inline bool   isHex() { return ishex; }
};
}

//
//  Message.cpp
//  Cicada
//
//  Created by Pierre Chanquion on 06/09/2014.
//

#include "Message.h"#include "easylogging++.h"#include "Utilities.h"#include <iomanip>
#include <iostream>
#include <string>
using namespace std;
using namespace Cicada;
using namespace Cicada::Utilities;

const size_t Cicada::Message::header_length = 10;
// -----------------------------------------------
// Constructors
Cicada::Message::Message(string con, CTA cta, bool ishex){
this->content = con;
this->cta     = cta;
this->ishex   = ishex;

generateHeader();
generateUID();
}
Cicada::Message::Message(){
cta   = CTA::UNKNOWN;
ishex = false;
}
Cicada::Message::~Message(){}

// -----------------------------------------------
// Print message to console
void Cicada::Message::print(){
cout << "====> CICADA MESSAGE" << endl;
cout << "\t===> CTA     : "   << cta             << endl;
cout << "\t===> CONTENT : "   << content        << endl;
cout << "\t===> SIZE    : "   << content.length() << " Bytes" <<endl;
}

// -----------------------------------------------
// Generate a header string for this message
void Cicada::Message::generateHeader(){
ostringstream ss;
ss << "SU"<< setfill('0') << setw(2) << cta << "N" << setfill('0') << setw(4) << content.length() << "T";
header = ss.str();
}

// -----------------------------------------------
// Generate UID
void Cicada::Message::generateUID(){

string s = toString();
uid      = 0;
for (char &c : s)
uid = uid * 101 + c;
}

// -----------------------------------------------
// Parse message
RC Cicada::Message::parse(string m, bool hex){

LOG(INFO) << "Parsing Message...";

ostringstream ss;
string        h, c;
size_t        s;
short         _0 = 48, _9 = 57;
CTA           _cta;
RC            r = RC::SUCCESS;

// Compartor: check whether value is within a particular range
auto in_range   = [] (int n, int mn, int mx) { return (n >= mn && n <= 57); };

// Generate error codes
auto error_code = [] (RC _r, RC _c) { return static_cast<RC>(_r == RC::SUCCESS ? _c : _r | _c); };

// Check Header Length
LOG(INFO) << "Check Header Length.";
auto v = split(m, "T");

if(v.size() == 1 || v[0].length() < header_length-1){
LOG(ERROR) << "Corrupt Header: LENGTH INVALID!";
r = error_code(r, RC::ERR_CORRUPT_HEADER);
if(ecl == B_STRICT_PARSE) return r;
}
ss << v[0] << "T";
h  =  ss.str(); // Header
c  = v[1];      // Content

LOG(INFO) << "Check Payload Length.";
if((hex && (c.length()-1) % 2 != 0) || c.length() == 0){
LOG(ERROR) << "Corrupt Payload: LENGTH INVALID!";
r = error_code(r, RC::ERR_CORRUPT_PAYLOAD);
if(ecl == B_STRICT_PARSE) return r;
}
LOG(INFO) << "Dehex String.";
// Dehex string
if(hex) c = hexStringToString(split(c, "Y")[0]);

// Check CTA Chunk
LOG(INFO) << "Check CTA Chunk.";
string t = h.substr(1,3);
if(t[0] != 'U' || !in_range(t[1], _0, _9) || !in_range(t[2], _0, _9)){
LOG(ERROR) << "Corrupt Header: CTA CHUNK INVALID!";
r = error_code(r, RC::ERR_CORRUPT_HEADER);
if(ecl == B_STRICT_PARSE) return r;
}
_cta = (CTA) atoi(t.substr(1).c_str());

// Check Length Chunk
LOG(INFO) << "Check Length Chunk.";
t = h.substr(4, 5);
if(t[0] != 'N' || !in_range(t[1], _0, _9) || !in_range(t[2], _0, _9) || !in_range(t[3], _0, _9) || !in_range(t[4], _0, _9)){
LOG(ERROR) << "Corrupt Header: SIZE CHUNK INVALID!";
r = error_code(r, RC::ERR_CORRUPT_HEADER);
if(ecl == B_STRICT_PARSE) return r;
}
s = atoi(t.substr(1).c_str());

LOG(INFO) << "Check Content Chunk.";
// Check content chunk
if(s != c.length()){
LOG(ERROR) << "Corrupt Payload: LENGTH DOES NOT MATCH HEADER SIZE CHUNK VALUE!";
r = error_code(r, RC::ERR_CORRUPT_PAYLOAD);
if(ecl == B_STRICT_PARSE) return r;
}

// Set content and cta.
content = c;
cta     = _cta;

// Generate header string
generateHeader();

LOG(INFO) << "Message Parsed => content="<<content<<" cta="<<cta;

return r;
}

// -----------------------------------------------
// Concatenates header and content
string Cicada::Message::toString(){
ostringstream ss;
ss << header << content;
return ss.str();
}

// -----------------------------------------------
// Saves Message to file
RC Cicada::Message::save(const string &fp){

ofstream outfile;
ostringstream ss;

// Append file type to fp
ss << fp << ".bin";

// Open File
outfile.open(ss.str().c_str(), ios::binary);
if (!outfile.is_open()) {
LOG(ERROR) << "Unable to open file at filepath: " << ss.str();
return RC::ERR_OPENING_FILE;
}

// Write to File
outfile << "CTA: " << cta     << "\n";
outfile << "CONTENT: " << content << "\n";

outfile.close();

return RC::SUCCESS;
}

// -----------------------------------------------
// Loads Message from file
RC Cicada::Message::load(const string &fp){

ifstream  infile;
ostringstream ss;

// Append file type to fp
ss << fp << ".bin";

// Open File
infile.open(ss.str().c_str(), ios::binary);
if (!infile.is_open()) {
LOG(ERROR) << "Unable to open file at filepath: " << ss.str().c_str();
return RC::ERR_OPENING_FILE;
}

// Read From File
while (infile.good()) {
string row;
if (getline(infile, row)) {
auto s = Utilities::split(row, ": ");
if(s.at(0) == "CTA")
cta = (CTA) atoi(s.at(1).c_str());
else if(s.at(0) == "CONTENT")
content = s.at(1);
}
}

return RC::SUCCESS;
}

// -----------------------------------------------
// Convert content to hex version
void Cicada::Message::hexifyContent(){
ostringstream c;
c << Utilities::stringToHexString(content) << "Y";
content = c.str();
ishex   = true;
}

// -----------------------------------------------
// Convert hex content to original version
void Cicada::Message::dehexifyContent(){
content = Utilities::hexStringToString(split(content, "Y")[0]);
ishex   = false;
}

// -----------------------------------------------
// Set content and generate header/UID
void Cicada::Message::setContent(string con) {
content = con;
generateHeader();
generateUID();
}

// -----------------------------------------------
// Set content and generate header/UID
void Cicada::Message::setCTA(CTA cta) {
this->cta = cta;
generateHeader();
generateUID();
}

Изменить: вот из приложения: настройка …

void ofApp::setup(){

try {
buffer = new float[ws]();
inwavebuf = new float[ws]();
} catch (bad_alloc e) {
cout << "Unable to allocate memory for " << e.what() << endl;
exit();
}

message.hexifyContent();
message.dehexifyContent();
message.getContent();
message.getCTA();
message.getHeader();
message.generateUID();
message.generateHeader();
message.getUID();
message.isHex();
message.load("");
message.save("");
message.toString();
message.setHex(true);
message.setECL(B_STRICT_PARSE);
message.print();
message.setContent("");
message.setCTA(UNKNOWN);
message.parse("010003414243", true);
message = Message("", UNKNOWN);

Message *msg = new Message("", UNKNOWN);

ofBackground(0);
setupGui();

}

1

Решение

Оказывается, Openframeworks не нравится двоичные файлы C ++ 11 … Я исправил это, не используя открытые платформы для рассматриваемого приложения.

0

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


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