我正在使用KWallet编写具有可选运行时依赖项的应用程序。这意味着如果在用户系统上安装了KWallet,它将被使用,如果不是,它仍然可以工作,但是没有KWallet支持。
这是我加载库的方式,它是包装类的静态属性。然后在状态下的构造函数中,我从库中解析符号。
QLibrary Core::PSE::KWallet::lib("KF5Wallet");
...
lib.load();
openWallet = (OpenWallet) lib.resolve("_ZN7KWallet6Wallet10openWalletERK7QStringyNS0_8OpenTypeE");
networkWallet = (NetworkWallet) lib.resolve("_ZN7KWallet6Wallet13NetworkWalletEv");
destructor = (Destructor) lib.resolve("_ZN7KWallet6WalletD2Ev");
与QLibrary相同-函数也是类的静态成员,但我不确定这是否是一个好主意。
这是我类的定义
typedef ::KWallet::Wallet* (*OpenWallet)(const QString &, WId, ::KWallet::Wallet::OpenType);
typedef QString (*NetworkWallet)();
typedef void (*WalletOpened)(bool);
typedef void (*Destructor)();
static OpenWallet openWallet;
static NetworkWallet networkWallet;
static Destructor destructor;
这是我分配对象的方式
wallet = openWallet(networkWallet(), 0, ::KWallet::Wallet::Asynchronous);
一切正常,直到需要执行非静态成员,尤其是析构函数为止。据我所知,应该看起来像那样
((*wallet).(destructor))()
但这似乎不起作用。我是这个主题的新手,即使我以正确的方式开始,我也不知道。
那么,如何调用这种方式加载的类的析构函数呢?如何调用其他成员?还是我最好以完全其他的方式来做?
附言我知道,有一个用于KWallet的DBUS API,甚至还有一些包装器库,例如qtkeychain,但我想了解使用此示例进行这种依赖的方式。
最佳答案
我找到了解决方案。
这个想法是用包装函数编写一个小的共享库
extern "C" KWallet::Wallet* openWallet(const QString &name, WId w, KWallet::Wallet::OpenType ot = KWallet::Wallet::Synchronous) {
return KWallet::Wallet::openWallet(name, w, ot);
}
extern "C" void deleteWallet(KWallet::Wallet* w) {
w->deleteLater();
}
extern "C" const char* networkWallet() {
return KWallet::Wallet::NetworkWallet().toStdString().c_str();
}
extern "C" int readPassword(KWallet::Wallet* w, const QString &key, QString &value) {
return w->readPassword(key, value);
}
我们将此小包装器称为
foo.so
。因此,然后在构建时构建此foo.so
并目标链接到实际依赖项(在我的情况下为KWallet
)。然后在主代码中,您将尝试动态加载此
foo.so
,而不是KWallet
本身。如果启动计算机上不存在KWallet
,则该foo.so
根本不会加载,而是我必须知道的窍门! 然后,您当然可以像这样解析符号
QLibrary Core::PSE::KWallet::lib("foo");
...
lib.load();
openWallet = (OpenWallet) lib.resolve("openWallet");
networkWallet = (NetworkWallet) lib.resolve("networkWallet");
deleteWallet = (DeleteWallet) lib.resolve("deleteWallet");
readPassword = (ReadPassword) lib.resolve("readPassword");
然后这样称呼它
wallet = openWallet(networkWallet(), 0, ::KWallet::Wallet::Asynchronous);
...
QString password;
int result = readPassword(wallet, *i, password);
...
deleteWallet(wallet);
关于c++ - 调用动态加载的库的非静态类成员函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61120185/