资讯动态

鸿蒙笔记3:用Lazarus程序取得资源文件路径

发布时间:2026/8/5 23:26:52 来源:尧图企业网站定制
目录1 简介2 Lazarus要读写的文件夹放在哪3 增加 napi_init.cpp4 修改原有的 libLazarusOHOS_Wrapper.cpp5 编译libLazarusOHOS_Wrapper.cpp6 鸿蒙项目增加文件 libLazarusOHOS_Wrapper.d.ts7 鸿蒙项目修改文件 QAbilityStage.ets8 lazarus 程序增加一个单元 OHOSPaths9 修改Lazarus程序主窗体代码10 运行结果本文基于秋风的10多篇lazarus鸿蒙开发博文及资源整理修改 秋·风 - 博客园1 简介鸿蒙应用安装后资源被自动解压到应用沙箱路径中通过 context.resourceDir 获取目录后可直接以文件路径访问只读。如果需要读写操作需要先将文件复制到 filesDir 沙箱目录中。Lazarus程序不能直接使用 context.resourceDir需要采取另外办法取得该路径进行读写操作。另外不同环境下这些目录不同不能写死在Lazarus程序中。秋风的博客内容及资源成功解决了鸿蒙与Lazarus的整合在特定细节需求方面需要自行修改完善。本文简要介绍鸿蒙打包lazarus程序如何获取资源的准确路径。2 Lazarus要读写的文件夹放在哪Lazarus需要读写的文件夹假设是cust_data 放在鸿蒙项目目录\entry\src\main\resources\resfile3 增加 napi_init.cpp在1.LazarusOHOS_Wrapper文件夹中增加 napi_init.cpp负责从 AbilityContext 中提取路径并提供给 Lazarus 侧使用。内容// 这个文件负责从 AbilityContext 中提取路径并提供给 Lazarus 侧使用 // napi_init.cpp #include napi/native_api.h #include cstring #include hilog/log.h // 缓存真实沙箱路径静态存储与 OHOS_GetFilesDir 等共享 static char g_realFilesDir[1024] {0}; static char g_realCacheDir[1024] {0}; static char g_realResourceDir[1024] {0}; static bool g_pathsReady false; // 辅助函数从 context 对象获取字符串属性并缓存 static bool GetAndCachePath(napi_env env, napi_value context, const char* propertyName, char* buffer, size_t bufSize) { napi_value prop; napi_status status napi_get_named_property(env, context, propertyName, prop); if (status ! napi_ok) { OH_LOG_ERROR(LOG_APP, [NAPI] Failed to get property: %{public}s, propertyName); return false; } // 可能返回的是 resourceManager 或 FilePath 对象需要区分处理 // 对于 filesDir/cacheDir/resourceDir在 context 下通常是直接字符串或 getter 函数 // HarmonyOS API 9 中 context.filesDir 直接返回 string size_t strLen 0; status napi_get_value_string_utf8(env, prop, buffer, bufSize, strLen); if (status ! napi_ok) { OH_LOG_ERROR(LOG_APP, [NAPI] Failed to get string for: %{public}s, propertyName); return false; } buffer[strLen] \0; OH_LOG_INFO(LOG_APP, [NAPI] %{public}s %{public}s, propertyName, buffer); return true; } // 外部可调用的初始化接口 extern C __attribute__((visibility(default))) napi_value OHOS_InitPaths(napi_env env, napi_callback_info info) { size_t argc 1; napi_value args[1]; napi_status status napi_get_cb_info(env, info, argc, args, nullptr, nullptr); if (status ! napi_ok || argc 1) { OH_LOG_ERROR(LOG_APP, [NAPI] OHOS_InitPaths: No context provided); napi_value ret; napi_get_boolean(env, false, ret); return ret; } napi_value context args[0]; // 依次获取路径 bool success true; success GetAndCachePath(env, context, filesDir, g_realFilesDir, sizeof(g_realFilesDir)); success GetAndCachePath(env, context, cacheDir, g_realCacheDir, sizeof(g_realCacheDir)); success GetAndCachePath(env, context, resourceDir, g_realResourceDir, sizeof(g_realResourceDir)); g_pathsReady success; napi_value result; napi_get_boolean(env, success, result); return result; } // Lazarus 侧调用的 C 接口替代原来依赖 Qt 的函数 extern C const char* OHOS_GetFilesDir() { if (g_pathsReady) return g_realFilesDir; else return ; // 未初始化时返回空串 } extern C const char* OHOS_GetCacheDir() { if (g_pathsReady) return g_realCacheDir; else return ; } extern C const char* OHOS_GetResourceDir() { if (g_pathsReady) return g_realResourceDir; else return ; } // NAPI 模块注册 static napi_value RegisterInitPaths(napi_env env, napi_value exports) { napi_property_descriptor desc[] { {OHOS_InitPaths, nullptr, OHOS_InitPaths, nullptr, nullptr, nullptr, napi_default, nullptr} }; napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); return exports; } static napi_module demoModule { .nm_version 1, .nm_flags 0, .nm_filename nullptr, .nm_register_func RegisterInitPaths, .nm_modname lazarusohos, .nm_priv nullptr, .reserved {0}, }; extern C __attribute__((constructor)) void RegisterModule(void) { napi_module_register(demoModule); }4 修改原有的 libLazarusOHOS_Wrapper.cpp内容为// libLazarusOHOS_Wrapper.cpp - HarmonyOS Qt5 Lazarus LCL wrapper // QApplication is already created by Qt OHOS plugin (libqohos.so) // before this library is loaded. Do NOT create another one. // 现在 OHOS_GetFilesDir 等函数已经在 napi_init.cpp 中实现了 // 原来的 wrapper 就不需要再通过 Qt 获取路径了 // 可以保留 wrapper 的 main 函数用于加载 Lazarus 库 // 但删除路径获取代码。 // libLazarusOHOS_Wrapper.cpp #include cstdio #include dlfcn.h // 路径函数声明由 napi_init.cpp 提供这里不用定义 extern C const char* OHOS_GetFilesDir(); extern C const char* OHOS_GetCacheDir(); extern C const char* OHOS_GetBundleDir(); // 不再使用可留空实现返回 typedef void (*InitAndShowFormFunc)(); extern C int main(int, char**) { // 此时路径可能还未初始化打印为空 fprintf(stderr, [Wrapper] OHOS_GetFilesDir: %s\n, OHOS_GetFilesDir()); fprintf(stderr, [Wrapper] OHOS_GetCacheDir: %s\n, OHOS_GetCacheDir()); // QApplication already exists from libqohos.so void* lib dlopen(libOHOS_QT_Lazarus.so, RTLD_NOW | RTLD_GLOBAL); if (!lib) { fprintf(stderr, [Wrapper] dlopen failed: %s\n, dlerror()); return 1; } InitAndShowFormFunc InitAndShowForm (InitAndShowFormFunc)dlsym(lib, InitAndShowForm); if (!InitAndShowForm) { fprintf(stderr, [Wrapper] dlsym failed: %s\n, dlerror()); dlclose(lib); return 1; } InitAndShowForm(); return 0; }5 编译libLazarusOHOS_Wrapper.cpp执行以下指令生成 aarch64 格式的so文件。为了访问hap包安装后的资源文件目录和沙箱目录此处经过修改与原文有所不同。原文指令lazarus鸿蒙开发3编译libLazarusOHOS_Wrapper.so - 秋·风 - 博客园注意先删除原来存在的文件 libLazarusOHOS_Wrapper.soSET NATIVE_OHOS_SDKd:/fpc4ohos/sdk/default/openharmony/native SET SYSROOT%NATIVE_OHOS_SDK%/sysroot SET QT5DIRd:/oh/Qt-5.12.12-ohos-aarch64 %NATIVE_OHOS_SDK%\llvm\bin\clang -shared ^ -o libLazarusOHOS_Wrapper.so ^ -I%SYSROOT%\usr\include ^ -I%SYSROOT%\usr\include\napi ^ -I%QT5DIR%\include ^ -I%QT5DIR%\include\QtCore ^ -I%QT5DIR%\include\QtGui ^ -I%QT5DIR%\include\QtWidgets ^ -L%SYSROOT%\usr\lib\aarch64-linux-ohos ^ -L%QT5DIR%\lib ^ -lace_napi.z ^ -lQt5Core ^ -lQt5Gui ^ -lQt5Widgets ^ -lc ^ -ldl ^ --sysroot%SYSROOT% ^ -target aarch64-linux-ohos ^ -fPIC ^ napi_init.cpp ^ libLazarusOHOS_Wrapper.cpp执行以下指令生成 x86_64 格式的so文件。为了访问hap包安装后的资源文件目录和沙箱目录此处经过修改与原文有所不同。原文指令lazarus鸿蒙开发3编译libLazarusOHOS_Wrapper.so - 秋·风 - 博客园SET NATIVE_OHOS_SDKd:/fpc4ohos/sdk/default/openharmony/native SET SYSROOT%NATIVE_OHOS_SDK%/sysroot SET QT5DIRd:/oh/Qt-5.12.12-ohos-x86_64 %NATIVE_OHOS_SDK%\llvm\bin\clang -shared ^ -o libLazarusOHOS_Wrapper.so ^ -I%SYSROOT%\usr\include ^ -I%SYSROOT%\usr\include\napi ^ -I%QT5DIR%\include ^ -I%QT5DIR%\include\QtCore ^ -I%QT5DIR%\include\QtGui ^ -I%QT5DIR%\include\QtWidgets ^ -L%SYSROOT%\usr\lib\x86_64-linux-ohos ^ -L%QT5DIR%\lib ^ -lace_napi.z ^ -lQt5Core ^ -lQt5Gui ^ -lQt5Widgets ^ -lc ^ -ldl ^ --sysroot%SYSROOT% ^ -target x86_64-linux-ohos ^ -fPIC ^ napi_init.cpp ^ libLazarusOHOS_Wrapper.cpp6 鸿蒙项目增加文件 libLazarusOHOS_Wrapper.d.tsD:\fpc4ohos\ohos_demo\2.ohos_hap_project\entry\src\main\ets\common\libLazarusOHOS_Wrapper.d.ts内容为// entry/src/main/ets/common/libLazarusOHOS_Wrapper.d.ts export interface Wrapper { OHOS_InitPaths(context: object): boolean; } declare const wrapper: Wrapper; export default wrapper;7 鸿蒙项目修改文件 QAbilityStage.etsD:\fpc4ohos\ohos_demo\2.ohos_hap_project\entry\src\main\ets\qabilitystage\QAbilityStage.ets代码// import lazarushos from libLazarusOHOS_Wrapper.so; // 新增导入 import lazarushos from libLazarusOHOS_Wrapper.so; import { Wrapper } from ../common/libLazarusOHOS_Wrapper; // 导入接口 // import AbilityStage from ohos.app.ability.AbilityStage; import QAbility from ../qability/QAbility; import QChildProcess from ../process/QChildProcess; import QtUtils from ../qability/QtUtils; import Want from ohos.app.ability.Want; import common from ohos.app.ability.common; import hilog from ohos.hilog; import qpa from libqohos.so; import {APP_LIBRARY_NAME, LOG_DOMAIN, LOG_TAG} from ../common/QtAppConstants; import { AbilityStage } from kit.AbilityKit; import { fileIo } from kit.CoreFileKit; export default class QAbilityStage extends AbilityStage { // setting appArgs overrides arguments from initial Want object private static appArgs?: Arraystring; private static setupQtApplicationCalled: boolean false; private static initQtAppContextImpl(appContext: common.ApplicationContext, abilityClassName: string, uiExtensionMode: boolean): void { if (!QAbilityStage.setupQtApplicationCalled) { hilog.info(LOG_DOMAIN, LOG_TAG, ccc QAbilityStage::initQtAppContextImpl: init with uiExtensionMode uiExtensionMode); QAbilityStage.setupQtApplicationCalled true; qpa.setupQtApplication({ appContext: appContext, modules: QtUtils.getModulesMapForQt(), appName: APP_LIBRARY_NAME, appArgs: QAbilityStage.appArgs, abilityClassName: abilityClassName, uiExtensionMode: uiExtensionMode, _unusedQChildProcess: new QChildProcess(), }); } else { hilog.info(LOG_DOMAIN, LOG_TAG, ccc QAbilityStage::initQtAppContextImpl: already initialized); } } public static initQtAppContextIfNeeded(appContext: common.ApplicationContext): void { QAbilityStage.initQtAppContextImpl(appContext, QAbility.name, false); } public static initQtAppContextInUiExtensionMode(appContext: common.ApplicationContext, abilityClassName: string): void { QAbilityStage.initQtAppContextImpl(appContext, abilityClassName, true); } // 直接使用 fileIo.copyDirSync适用于层级少、文件小的场景 // public static copyDirSimple(srcPath: string, destPath: string): void { // // 检查目标目录是否已存在 // let destExists: boolean fileIo.accessSync(destPath, fileIo.AccessModeType.EXIST); // if (destExists) { // console.info(目标目录已存在跳过复制: ${destPath}); // return; // } // // 直接复制整个目录 // fileIo.copyDirSync(srcPath, destPath); // } onCreate(): void { hilog.info(LOG_DOMAIN, LOG_TAG, QAbilityStage::onCreate()); qpa.handleAbilityStageOnCreate(this); // 获取 AbilityStageContext let context: common.AbilityStageContext this.context; // 初始化 wrapper 的路径缓存必须在 wrapper.main 执行之前 try { // 直接通过 as 断言调用杜绝 any 类型 let initResult: boolean (lazarushos as Wrapper).OHOS_InitPaths(context); console.info(ccc [QAbilityStage] OHOS_InitPaths result: ${initResult}); } catch (e) { console.error(ccc [QAbilityStage] OHOS_InitPaths failed: ${e}); } // 获取 resfile 资源目录只读和 filesDir 沙箱目录可读写 let resourceDir: string context.resourceDir; let filesDir: string context.filesDir; console.info(ccc resourceDir: ${resourceDir}); console.info(ccc filesDir: ${filesDir}); } onNewProcessRequest(want: Want): string { hilog.info(LOG_DOMAIN, LOG_TAG, QAbilityStage::onNewProcessRequest: want.parameters: JSON.stringify(want.parameters)); QAbilityStage.initQtAppContextIfNeeded(this.context.getApplicationContext()); let processKey: string qpa.handleAbilityStageOnNewProcessRequest(this, want); hilog.info(LOG_DOMAIN, LOG_TAG, ccc QAbilityStage::onNewProcessRequest: processKey: processKey ); return processKey; } onAcceptWant(want: Want): string { hilog.info(LOG_DOMAIN, LOG_TAG, ccc QAbilityStage::onAcceptWant: want.parameters: JSON.stringify(want.parameters)); QAbilityStage.initQtAppContextIfNeeded(this.context.getApplicationContext()); let instanceKey: string qpa.handleAbilityStageOnAcceptWant(this, want); hilog.info(LOG_DOMAIN, LOG_TAG, ccc QAbilityStage::onAcceptWant: instanceKey: instanceKey ); return instanceKey; } onDestroy() { hilog.info(LOG_DOMAIN, LOG_TAG, ccc QAbilityStage::onDestroy()); qpa.handleAbilityStageOnDestroy(this); } }8 lazarus 程序增加一个单元 OHOSPathsunit OHOSPaths; interface uses SysUtils; //function OHOS_GetFilesDir: PChar; cdecl; external libLazarusOHOS_Wrapper.so; //function OHOS_GetCacheDir: PChar; cdecl; external libLazarusOHOS_Wrapper.so; //function OHOS_GetBundleDir: PChar; cdecl; external libLazarusOHOS_Wrapper.so; function OHOS_GetFilesDir: PChar; cdecl; external libLazarusOHOS_Wrapper.so; function OHOS_GetCacheDir: PChar; cdecl; external libLazarusOHOS_Wrapper.so; function OHOS_GetResourceDir: PChar; cdecl; external libLazarusOHOS_Wrapper.so; //function GetOHOSFilesPath: string; //function GetOHOSCachePath: string; //function GetOHOSBundlePath: string; function GetOHOSFilesPath: string; function GetOHOSResourcePath: string; function GetOHOSCachePath: string; implementation //function SafeStr(P: PChar): string; inline; //begin // if P nil then Result : else Result : StrPas(P); //end; // //function GetOHOSFilesPath: string; //begin // Result : SafeStr(OHOS_GetFilesDir); // if Result then Result : IncludeTrailingPathDelimiter(Result); //end; // //function GetOHOSCachePath: string; //begin // Result : SafeStr(OHOS_GetCacheDir); // if Result then Result : IncludeTrailingPathDelimiter(Result); //end; // //function GetOHOSBundlePath: string; //begin // Result : SafeStr(OHOS_GetBundleDir); // if Result then Result : IncludeTrailingPathDelimiter(Result); //end; function GetOHOSFilesPath: string; begin Result : string(AnsiString(OHOS_GetFilesDir)); end; function GetOHOSCachePath: string; begin Result : string(AnsiString(OHOS_GetCacheDir)); end; function GetOHOSResourcePath: string; begin Result : string(AnsiString(OHOS_GetResourceDir)); end; end.9 修改Lazarus程序主窗体代码uses OHOSPaths; ...... showmessage(format(GetOHOSFilesPath: %s, GetOHOSResourcePath: %s, [GetOHOSFilesPath, GetOHOSResourcePath])); ......10 运行结果DevEco模拟器中Lazarus程序弹出窗口

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价