这个错误是关于什么的?
What is this error about?
全部,
我正在使用 Anjuta 进行开发。
我为我的主应用程序创建了一个项目,然后又创建了 2 个:1 个用于静态库 (libdbinterface.a) 和 1 个用于动态库 (libsqlite_lib.so)。
这两个库都包含一个导出的 class:libdbinterface.a - class 数据库,libsqlite_lib.so - public SQLiteDatabase : public 数据库.
现在我正在尝试 link libdbinterface.a 到 libsqlite_lib.so。
所以在 Anjuta 中,我为目标 libsqlite_lib.so 添加了以下内容到 "Linker Option":
-L/home/igor/dbhandler/Debug/dbinterface -ldbinterface
但是,在尝试编译时我收到了来自 linker 的以下错误:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.4/../../../../x86_64-pc-linux-gnu/bin/ld: /home/igor/dbhandler/Debug/dbinterface/libdbinterface.a(database.o): relocation R_X86_64_32S against `_ZTV8Database' can not be used when making a shared object; recompile with -fPIC
我尝试重新编译 libsqlite_lib.so,并明确将 -fPIC 添加到该项目的 "C++ Options",但这并没有解决问题 - 我仍然收到同样的错误。
不幸的是,尝试 Google 如何 link .a 和 .so 没有帮助。
有人可以详细说明如何修复此错误吗?
TIA。
[编辑]
libsqlite_lib.so 生成文件 - https://bpaste.net/show/1495231e58cc
libdbinterface.a 生成文件 - https://bpaste.net/show/3a71c119d0fc
libdbinterface.a 包含 2 个文件 databse.h:
#ifndef DBMANAGER_DATABASE
#define DBMANAGER_DATABASE
class Field
{
public:
Field(const std::string &columnName, const std::string &columnType, const std::string &columnDefaultValue = "", const bool columnIsNull = false, const bool columnPK = false)
{
column_name = columnName;
column_type = columnType;
column_defaultValue = columnDefaultValue;
column_isNull = columnIsNull;
column_pk = columnPK;
}
private:
std::string column_name, column_type, column_defaultValue;
bool column_isNull, column_pk;
};
struct FKField
{
FKField(const std::string &table_name, const std::string &original_field, const std::string &referenced_field)
{
tableName = table_name;
originalField = original_field;
referencedField = referenced_field;
}
std::string tableName, originalField, referencedField;
};
class Table
{
public:
Table(const std::string &tableName, const std::vector<Field> &tableFields, const std::map<int,std::vector<FKField> > &foreignKeys)
{
table_name = tableName;
table_fields = tableFields;
foreign_keys = foreignKeys;
}
const std::string &GetTableName() { return table_name; }
std::map<int,std::vector<FKField> > &GetForeignKeyVector() { return foreign_keys; }
private:
std::string table_name;
std::vector<Field> table_fields;
std::map<int,std::vector<FKField> > foreign_keys;
};
#ifdef WIN32
class __declspec(dllexport) Database
#else
class Database
#endif
{
private:
struct Impl;
Impl *pimpl;
public:
Database();
virtual ~Database();
Impl &GetTableVector();
static void *operator new(std::size_t size);
static void operator delete(void *ptr, std::size_t size);
virtual int Connect(const char *selectedDSN, std::vector<std::wstring> &errorMsg);
virtual int GetTableListFromDb(std::string &) { return 0; }
};
#endif
和database.cpp:
#ifdef WIN32
#include <windows.h>
#endif
#include <map>
#include <vector>
#include <string>
#include <sqlext.h>
#include "database.h"
struct Database::Impl
{
std::vector<Table> m_tables;
};
Database::Database() : pimpl( new Impl )
{
}
Database::~Database()
{
delete pimpl;
}
void *Database::operator new(std::size_t size)
{
return ::operator new( size );
}
void Database::operator delete(void *ptr, std::size_t size)
{
return ::operator delete( ptr );
}
Database::Impl &Database::GetTableVector()
{
return *pimpl;
}
int Database::Connect(const char *selectedDSN, std::vector<std::wstring> &errorMsg)
{
selectedDSN = selectedDSN;
errorMsg = errorMsg;
return 0;
}
libsqlite_lib.so 还有 2 个文件:database_sqlite.h
#ifndef DBMANAGER_SQLITE
#define DBMANAGER_SQLITE
#ifdef WIN32
class __declspec(dllexport) SQLiteDatabase : public Database
#else
class SQLiteDatabase : public Database
#endif
{
public:
SQLiteDatabase();
~SQLiteDatabase();
virtual int Connect(const char *selectedDSN, std::vector<std::wstring> &errorMsg);
virtual int GetTableListFromDb(std::vector<std::wstring> &errorMsg);
protected:
void GetErrorMessage(int code, std::wstring &errorMsg);
private:
sqlite3 *m_db;
};
#endif
和 database_sqlite.cpp 与实际实施。
[/编辑]
嗯,显然解决方案是用“-fPIC”重建静态库,而不是动态库。
感谢您的阅读。
全部,
我正在使用 Anjuta 进行开发。
我为我的主应用程序创建了一个项目,然后又创建了 2 个:1 个用于静态库 (libdbinterface.a) 和 1 个用于动态库 (libsqlite_lib.so)。
这两个库都包含一个导出的 class:libdbinterface.a - class 数据库,libsqlite_lib.so - public SQLiteDatabase : public 数据库.
现在我正在尝试 link libdbinterface.a 到 libsqlite_lib.so。
所以在 Anjuta 中,我为目标 libsqlite_lib.so 添加了以下内容到 "Linker Option":
-L/home/igor/dbhandler/Debug/dbinterface -ldbinterface
但是,在尝试编译时我收到了来自 linker 的以下错误:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.4/../../../../x86_64-pc-linux-gnu/bin/ld: /home/igor/dbhandler/Debug/dbinterface/libdbinterface.a(database.o): relocation R_X86_64_32S against `_ZTV8Database' can not be used when making a shared object; recompile with -fPIC
我尝试重新编译 libsqlite_lib.so,并明确将 -fPIC 添加到该项目的 "C++ Options",但这并没有解决问题 - 我仍然收到同样的错误。
不幸的是,尝试 Google 如何 link .a 和 .so 没有帮助。
有人可以详细说明如何修复此错误吗?
TIA。
[编辑] libsqlite_lib.so 生成文件 - https://bpaste.net/show/1495231e58cc libdbinterface.a 生成文件 - https://bpaste.net/show/3a71c119d0fc
libdbinterface.a 包含 2 个文件 databse.h:
#ifndef DBMANAGER_DATABASE
#define DBMANAGER_DATABASE
class Field
{
public:
Field(const std::string &columnName, const std::string &columnType, const std::string &columnDefaultValue = "", const bool columnIsNull = false, const bool columnPK = false)
{
column_name = columnName;
column_type = columnType;
column_defaultValue = columnDefaultValue;
column_isNull = columnIsNull;
column_pk = columnPK;
}
private:
std::string column_name, column_type, column_defaultValue;
bool column_isNull, column_pk;
};
struct FKField
{
FKField(const std::string &table_name, const std::string &original_field, const std::string &referenced_field)
{
tableName = table_name;
originalField = original_field;
referencedField = referenced_field;
}
std::string tableName, originalField, referencedField;
};
class Table
{
public:
Table(const std::string &tableName, const std::vector<Field> &tableFields, const std::map<int,std::vector<FKField> > &foreignKeys)
{
table_name = tableName;
table_fields = tableFields;
foreign_keys = foreignKeys;
}
const std::string &GetTableName() { return table_name; }
std::map<int,std::vector<FKField> > &GetForeignKeyVector() { return foreign_keys; }
private:
std::string table_name;
std::vector<Field> table_fields;
std::map<int,std::vector<FKField> > foreign_keys;
};
#ifdef WIN32
class __declspec(dllexport) Database
#else
class Database
#endif
{
private:
struct Impl;
Impl *pimpl;
public:
Database();
virtual ~Database();
Impl &GetTableVector();
static void *operator new(std::size_t size);
static void operator delete(void *ptr, std::size_t size);
virtual int Connect(const char *selectedDSN, std::vector<std::wstring> &errorMsg);
virtual int GetTableListFromDb(std::string &) { return 0; }
};
#endif
和database.cpp:
#ifdef WIN32
#include <windows.h>
#endif
#include <map>
#include <vector>
#include <string>
#include <sqlext.h>
#include "database.h"
struct Database::Impl
{
std::vector<Table> m_tables;
};
Database::Database() : pimpl( new Impl )
{
}
Database::~Database()
{
delete pimpl;
}
void *Database::operator new(std::size_t size)
{
return ::operator new( size );
}
void Database::operator delete(void *ptr, std::size_t size)
{
return ::operator delete( ptr );
}
Database::Impl &Database::GetTableVector()
{
return *pimpl;
}
int Database::Connect(const char *selectedDSN, std::vector<std::wstring> &errorMsg)
{
selectedDSN = selectedDSN;
errorMsg = errorMsg;
return 0;
}
libsqlite_lib.so 还有 2 个文件:database_sqlite.h
#ifndef DBMANAGER_SQLITE
#define DBMANAGER_SQLITE
#ifdef WIN32
class __declspec(dllexport) SQLiteDatabase : public Database
#else
class SQLiteDatabase : public Database
#endif
{
public:
SQLiteDatabase();
~SQLiteDatabase();
virtual int Connect(const char *selectedDSN, std::vector<std::wstring> &errorMsg);
virtual int GetTableListFromDb(std::vector<std::wstring> &errorMsg);
protected:
void GetErrorMessage(int code, std::wstring &errorMsg);
private:
sqlite3 *m_db;
};
#endif
和 database_sqlite.cpp 与实际实施。 [/编辑]
嗯,显然解决方案是用“-fPIC”重建静态库,而不是动态库。
感谢您的阅读。