我一直在开发C ++动态库,在xcode命令行界面项目和gtest项目中进行测试时,该库可以编译并运行。
但是,当我尝试在openframeworks项目中链接它时,链接器抱怨无法为我的一个类的某些功能找到i386符号。这尤其奇怪,因为它可以看到21个函数,构造函数和析构函数中的16个符号...我知道这是因为我可以调用所有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打电话:
> 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,解析,保存和加载。
我知道64位功能仅在版本9中才出现在openframeworks中,因此可以编译通用二进制文件。我什至尝试专门为i386编译,但是没有骰子。
我已经为openframeworks项目尝试了各种体系结构和SDK,但是除默认$(NATIVE_ARCH)以外的其他任何内容都阻止了openframeworks自身的编译。库搜索路径指向正确的位置,并且在构建阶段中我正在链接到正确的库,这很明显,因为当对有问题的函数的调用被注释掉时,它会愉快地编译并运行。
我有点this,这是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();
}
编辑:这是ofApp:setup ...
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();
}
事实证明,Openframeworks不喜欢C ++ 11二进制文件。我通过不使用有问题的应用程序的开放框架来解决此问题。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句