我试图将自定义CodeInsight管理器注册到C ++ Builder 10.1.2 Berlin。
因为在C ++中没有像 Objects Pascal 的initialization
和finalization
部分,例如。
var
codeManagerIndex: Integer;
{...}
initialization
codeManagerIndex := (BorlandIDEServices as IOTACodeInsightServices).AddCodeInsightManager(TMyCodeInsightManager.Create);
finalization
(borlandIDEServices as IOTACodeInsightServices).RemoveCodeInsightManager(codeManagerIndex);
end.
我尝试使用带有构造函数/析构函数的自定义runner
类来重现他们的行为:
class Runner
{
public:
int FCodeManagerIndex;
_di_IOTACodeInsightServices CIS;
Runner() {
if (BorlandIDEServices->Supports(CIS))
FCodeManagerIndex = CIS->AddCodeInsightManager(new TMyCodeInsightManager);
}
~Runner() {
if (BorlandIDEServices->Supports(CIS))
CIS->RemoveCodeInsightManager(FCodeManagerIndex);
}
};
#pragma argsused
extern "C" int _libmain(unsigned long reason)
{
Runner Run;
return 1;
}
我可以编译我的简单实现,但是当我尝试安装软件包时,会发生以下情况:
第一次尝试:错误消息:无法加载包... mypackage.bpl - 动态链接库(DLL)初始化例程失败。
第二次尝试:模块中的DllEntryPoint或DllMain期间发生异常(C0000005):... mypackage.bpl ...然后IDE崩溃。
这是一种错误的注册方式吗? 我在这里做错了什么?
P.S。我收到 [TLIB警告]警告:库对于页面大小而言太大,在编译时重建了页面大小为32 的警告,但我确信这不是我的错误的原因。 (?)
答案 0 :(得分:3)
没有像C ++中的Objects Pascal的
initialization
和finalization
部分那样
实际上,有。在C ++ Builder中,您可以使用#pragma startup
and #pragma exit
来执行用户定义的函数:
static int FCodeManagerIndex = -1;
void DoRegister() {
_di_IOTACodeInsightServices CIS;
if (BorlandIDEServices->Supports(CIS)) {
FCodeManagerIndex = CIS->AddCodeInsightManager(new TMyCodeInsightManager);
}
}
#pragma startup DoRegister
void DoUnregister() {
_di_IOTACodeInsightServices CIS;
if ((FCodeManagerIndex != -1) && BorlandIDEServices->Supports(CIS)) {
CIS->RemoveCodeInsightManager(FCodeManagerIndex);
}
}
#pragma exit DoUnregister
#pragma argsused
extern "C" int _libmain(unsigned long reason)
{
return 1;
}
或者,既然您已经准备好声明一个类来处理您的注册,您可以简单地将您的类变量移动到全局静态内存中,以便其构造函数在启动时运行,析构函数在shutdown时运行:
class Runner
{
public:
int FCodeManagerIndex;
Runner() : FCodeManagerIndex(-1) {
_di_IOTACodeInsightServices CIS;
if (BorlandIDEServices->Supports(CIS)) {
FCodeManagerIndex = CIS->AddCodeInsightManager(new TMyCodeInsightManager);
}
}
~Runner() {
_di_IOTACodeInsightServices CIS;
if ((FCodeManagerIndex != -1) && BorlandIDEServices->Supports(CIS)) {
CIS->RemoveCodeInsightManager(FCodeManagerIndex);
}
}
};
static Runner Run;
#pragma argsused
extern "C" int _libmain(unsigned long reason)
{
return 1;
}
在_libmain()
内声明类变量是没用的,因为当_libmain()
退出时变量超出范围时将调用析构函数,因此在注册后立即取消注册管理器。因此,只要将包加载到内存中,变量就必须存活。