mirror of
https://github.com/fcitx5-android/fcitx5-android.git
synced 2026-08-02 04:44:35 +08:00
Fix loading addon library from plugins
partially reverts c57e8b4618d1380c9d1bac3d70bb1a331961daf0
This commit is contained in:
parent
e48d07125c
commit
7d408e61ca
@ -44,7 +44,7 @@ add_library(pinyin-customphrase STATIC "${CHINESE_ADDONS_PINYIN_DIR}/customphras
|
||||
target_include_directories(pinyin-customphrase INTERFACE "${CHINESE_ADDONS_PINYIN_DIR}")
|
||||
target_link_libraries(pinyin-customphrase PRIVATE Fcitx5::Utils LibIME::Core)
|
||||
|
||||
add_library(native-lib SHARED native-lib.cpp)
|
||||
add_library(native-lib SHARED native-lib.cpp androidaddonloader/androidaddonloader.cpp)
|
||||
target_link_libraries(native-lib
|
||||
log
|
||||
libuv::uv_a
|
||||
|
||||
102
app/src/main/cpp/androidaddonloader/androidaddonloader.cpp
Normal file
102
app/src/main/cpp/androidaddonloader/androidaddonloader.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
* SPDX-FileCopyrightText: Copyright 2016-2016 CSSlayer <wengxt@gmail.com>
|
||||
* SPDX-FileCopyrightText: Copyright 2023-2025 Fcitx5 for Android Contributors
|
||||
* SPDX-FileComment: Modified from https://github.com/fcitx/fcitx5/blob/5.1.14/src/lib/fcitx/addonloader.cpp
|
||||
*/
|
||||
|
||||
#include <exception>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <fcitx-utils/flags.h>
|
||||
#include <fcitx-utils/library.h>
|
||||
#include <fcitx-utils/log.h>
|
||||
#include <fcitx-utils/standardpaths.h>
|
||||
#include <fcitx-utils/stringutils.h>
|
||||
#include <fcitx/addoninfo.h>
|
||||
#include <fcitx/addoninstance.h>
|
||||
|
||||
#define FCITX_LIBRARY_SUFFIX ".so"
|
||||
|
||||
#include "androidaddonloader.h"
|
||||
|
||||
namespace fcitx {
|
||||
|
||||
AddonInstance *AndroidSharedLibraryLoader::load(const AddonInfo &info,
|
||||
AddonManager *manager) {
|
||||
auto iter = registry_.find(info.uniqueName());
|
||||
if (iter == registry_.end()) {
|
||||
std::vector<std::string> libnames =
|
||||
stringutils::split(info.library(), ";");
|
||||
|
||||
if (libnames.empty()) {
|
||||
FCITX_ERROR() << "Failed to parse Library field: " << info.library()
|
||||
<< " for addon " << info.uniqueName();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<Library> libraries;
|
||||
for (std::string_view libname: libnames) {
|
||||
Flags<LibraryLoadHint> flag = LibraryLoadHint::DefaultHint;
|
||||
if (stringutils::consumePrefix(libname, "export:")) {
|
||||
flag |= LibraryLoadHint::ExportExternalSymbolsHint;
|
||||
}
|
||||
const auto file =
|
||||
stringutils::concat(libname, FCITX_LIBRARY_SUFFIX);
|
||||
const auto libraryPaths = standardPaths_.locateAll(
|
||||
StandardPathsType::Addon, file);
|
||||
if (libraryPaths.empty()) {
|
||||
FCITX_ERROR() << "Could not locate library " << file
|
||||
<< " for addon " << info.uniqueName() << ".";
|
||||
}
|
||||
bool loaded = false;
|
||||
for (const auto &libraryPath: libraryPaths) {
|
||||
Library library(libraryPath);
|
||||
if (library.load(flag)) {
|
||||
libraries.push_back(std::move(library));
|
||||
loaded = true;
|
||||
break;
|
||||
}
|
||||
FCITX_ERROR()
|
||||
<< "Failed to load library for addon " << info.uniqueName()
|
||||
<< " on " << libraryPath << ". Error: " << library.error();
|
||||
}
|
||||
if (!loaded) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (libraries.size() == libnames.size()) {
|
||||
try {
|
||||
registry_.emplace(info.uniqueName(),
|
||||
std::make_unique<AndroidSharedLibraryFactory>(
|
||||
info, std::move(libraries)));
|
||||
} catch (const std::exception &e) {
|
||||
FCITX_ERROR() << "Failed to initialize addon factory for addon "
|
||||
<< info.uniqueName() << ". Error: " << e.what();
|
||||
}
|
||||
iter = registry_.find(info.uniqueName());
|
||||
}
|
||||
}
|
||||
|
||||
if (iter == registry_.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
try {
|
||||
return iter->second->factory()->create(manager);
|
||||
} catch (const std::exception &e) {
|
||||
FCITX_ERROR() << "Failed to create addon: " << info.uniqueName() << " "
|
||||
<< e.what();
|
||||
} catch (...) {
|
||||
FCITX_ERROR() << "Failed to create addon: " << info.uniqueName();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace fcitx
|
||||
85
app/src/main/cpp/androidaddonloader/androidaddonloader.h
Normal file
85
app/src/main/cpp/androidaddonloader/androidaddonloader.h
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
* SPDX-FileCopyrightText: Copyright 2016-2016 CSSlayer <wengxt@gmail.com>
|
||||
* SPDX-FileCopyrightText: Copyright 2023-2025 Fcitx5 for Android Contributors
|
||||
* SPDX-FileComment: Modified from https://github.com/fcitx/fcitx5/blob/5.1.14/src/lib/fcitx/addonloader_p.h
|
||||
*/
|
||||
|
||||
#ifndef FCITX5_ANDROID_ANDROIDADDONLOADER_H
|
||||
#define FCITX5_ANDROID_ANDROIDADDONLOADER_H
|
||||
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <fcitx-utils/library.h>
|
||||
#include <fcitx-utils/standardpaths.h>
|
||||
#include <fcitx-utils/stringutils.h>
|
||||
#include <fcitx/addonfactory.h>
|
||||
#include <fcitx/addoninfo.h>
|
||||
#include <fcitx/addoninstance.h>
|
||||
#include <fcitx/addonloader.h>
|
||||
|
||||
namespace fcitx {
|
||||
|
||||
namespace {
|
||||
constexpr char FCITX_ADDON_FACTORY_ENTRY[] = "fcitx_addon_factory_instance";
|
||||
}
|
||||
|
||||
class AndroidSharedLibraryFactory {
|
||||
public:
|
||||
explicit AndroidSharedLibraryFactory(const AddonInfo &info, std::vector<Library> libraries)
|
||||
: libraries_(std::move(libraries)) {
|
||||
std::string v2Name = stringutils::concat(FCITX_ADDON_FACTORY_ENTRY, "_",
|
||||
info.uniqueName());
|
||||
if (libraries_.empty()) {
|
||||
throw std::runtime_error("Got empty libraries.");
|
||||
}
|
||||
|
||||
// Only resolve with last library.
|
||||
auto &library = libraries_.back();
|
||||
auto *funcPtr = library.resolve(v2Name.data());
|
||||
if (!funcPtr) {
|
||||
funcPtr = library.resolve(FCITX_ADDON_FACTORY_ENTRY);
|
||||
}
|
||||
if (!funcPtr) {
|
||||
throw std::runtime_error(library.error());
|
||||
}
|
||||
auto func = Library::toFunction<AddonFactory *()>(funcPtr);
|
||||
factory_ = func();
|
||||
if (!factory_) {
|
||||
throw std::runtime_error("Failed to get a factory");
|
||||
}
|
||||
}
|
||||
|
||||
AddonFactory *factory() { return factory_; }
|
||||
|
||||
private:
|
||||
std::vector<Library> libraries_;
|
||||
AddonFactory *factory_;
|
||||
};
|
||||
|
||||
class AndroidSharedLibraryLoader : public AddonLoader {
|
||||
public:
|
||||
[[nodiscard]] std::string type() const override { return "SharedLibrary"; }
|
||||
|
||||
AddonInstance *load(const AddonInfo &info, AddonManager *manager) override;
|
||||
|
||||
private:
|
||||
// Android specific: create a new StandardPaths instance in case FCITX_ADDON_DIRS changes
|
||||
StandardPaths standardPaths_ = StandardPaths(
|
||||
"fcitx5",
|
||||
std::unordered_map<std::string, std::vector<std::filesystem::path>>{},
|
||||
Flags<StandardPathsOption>(StandardPathsOption::SkipBuiltInPath)
|
||||
);
|
||||
// Android specific end
|
||||
std::unordered_map<std::string, std::unique_ptr<AndroidSharedLibraryFactory>>
|
||||
registry_;
|
||||
};
|
||||
|
||||
} // namespace fcitx
|
||||
|
||||
#endif //FCITX5_ANDROID_ANDROIDADDONLOADER_H
|
||||
@ -40,6 +40,7 @@
|
||||
#include <boost/iostreams/stream_buffer.hpp>
|
||||
#include "customphrase.h"
|
||||
|
||||
#include "androidaddonloader/androidaddonloader.h"
|
||||
#include "androidfrontend/androidfrontend_public.h"
|
||||
#include "jni-utils.h"
|
||||
#include "nativestreambuf.h"
|
||||
@ -82,7 +83,7 @@ public:
|
||||
|
||||
void startup(const std::function<void(fcitx::AddonInstance *)> &setupCallback) {
|
||||
p_instance = std::make_unique<fcitx::Instance>(0, nullptr);
|
||||
p_instance->addonManager().registerDefaultLoader(nullptr);
|
||||
p_instance->addonManager().registerLoader(std::make_unique<fcitx::AndroidSharedLibraryLoader>());
|
||||
p_dispatcher = std::make_unique<fcitx::EventDispatcher>();
|
||||
p_dispatcher->attach(&p_instance->eventLoop());
|
||||
p_instance->initialize();
|
||||
@ -527,7 +528,10 @@ Java_org_fcitx_fcitx5_android_core_Fcitx_startupFcitx(
|
||||
const std::string data_home = fcitx::stringutils::joinPath(*extData_, "data");
|
||||
const std::string usr_share = fcitx::stringutils::joinPath(*appData_, "usr", "share");
|
||||
const std::string locale_dir = fcitx::stringutils::joinPath(usr_share, "locale");
|
||||
const std::string libime_data = fcitx::stringutils::joinPath(usr_share, "libime");
|
||||
const std::string libime_data = fcitx::stringutils::concat(
|
||||
fcitx::stringutils::joinPath(*extData_, "data", "libime"), ":",
|
||||
fcitx::stringutils::joinPath(usr_share, "libime")
|
||||
);
|
||||
const std::string lua_path = fcitx::stringutils::concat(
|
||||
fcitx::stringutils::joinPath(data_home, "lua", "?.lua"), ";",
|
||||
fcitx::stringutils::joinPath(data_home, "lua", "?", "init.lua"), ";",
|
||||
@ -542,7 +546,7 @@ Java_org_fcitx_fcitx5_android_core_Fcitx_startupFcitx(
|
||||
);
|
||||
|
||||
// prevent StandardPath from resolving it's hardcoded installation path
|
||||
setenv("SKIP_FCITX_PATH", "1", 1);
|
||||
// setenv("SKIP_FCITX_PATH", "1", 1);
|
||||
// for fcitx default profile [DefaultInputMethod]
|
||||
setenv("LANG", lang_.c_str(), 1);
|
||||
// for libintl-lite loading gettext .mo translations
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user