升级Delphi后BPL加载资源字符串失败,原因何在?
问题描述
我们有一个包含资源文件(.rc)的BPL,其中的字符串通过STRINGTABLE定义,使用LoadStr()加载。项目原基于Delphi 10.1 Berlin,升级至11.1 Alexandria后,LoadStr()调用返回NULL。
测试时在主函数中添加的代码可正常运行:
extern "C" int _libmain(unsigned long reason) { String str = LoadStr(231); // Works return 1; }
但现有导出函数无法工作:
.h
PACKAGE String __fastcall GetValueSetDesc(int ACount);
.cpp
String __fastcall GetValueSetDesc(int ACount) { String ValueDesc = LoadStr(ACount); // Does not work, returns NULL return ValueDesc; }
已尝试重新创建项目并添加文件,寻求问题原因及解决方法。
可能的原因与解决方法
1. 资源上下文未切换到BPL模块
在Delphi 11中,导出的PACKAGE函数可能默认使用主程序的资源句柄,而非BPL自身的资源句柄。_libmain执行时,模块的资源上下文是当前BPL,所以LoadStr能正常找到资源;但导出函数被调用时,资源上下文可能切换回了宿主程序。
解决方法:手动指定BPL的模块句柄加载字符串,替代LoadStr:
#include <Windows.hpp> #include <SysUtils.hpp> // 可选:在_libmain中保存当前模块句柄,避免硬编码文件名 HMODULE g_hModule = nullptr; extern "C" int _libmain(unsigned long reason) { if (reason == DLL_PROCESS_ATTACH) { g_hModule = GetModuleHandle(nullptr); // 获取当前BPL的模块句柄 } String str = LoadStr(231); return 1; } String __fastcall GetValueSetDesc(int ACount) { if (!g_hModule) return String(); wchar_t buffer[256]; int len = LoadStringW(g_hModule, ACount, buffer, sizeof(buffer)/sizeof(wchar_t)); return len > 0 ? String(buffer) : String(); }
2. 临时切换资源模块上下文
使用VCL的SetResourceModule函数,临时将资源查找上下文切换到当前BPL,执行完后恢复原上下文:
#include <SysUtils.hpp> String __fastcall GetValueSetDesc(int ACount) { HMODULE hBplModule = GetModuleHandle(nullptr); HMODULE hOldModule = SetResourceModule(hBplModule); String ValueDesc = LoadStr(ACount); SetResourceModule(hOldModule); // 恢复原资源模块上下文 return ValueDesc; }
3. 检查资源文件编译状态
确认资源文件在Delphi 11中是否正确编译到BPL:
- 检查BPL项目的资源文件引用是否有效,确保
.rc或.res文件已添加到项目中。 - 尝试手动编译资源文件:使用
brcc32工具将.rc编译为.res,再重新添加到项目并编译BPL。
内容的提问来源于stack exchange,提问作者MathewJoy
相关产品推荐
相关产品推荐

