将自定义CodeInsight管理器注册到C ++ Builder而不进行初始化/完成部分

时间:2017-01-29 16:03:46

标签: delphi c++builder

我试图将自定义CodeInsight管理器注册到C ++ Builder 10.1.2 Berlin。

因为在C ++中没有像 Objects Pascal initializationfinalization部分,例如。

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 的警告,但我确信这不是我的错误的原因。 (?)

1 个答案:

答案 0 :(得分:3)

  

没有像C ++中的Objects Pascal的initializationfinalization部分那样

实际上,有。在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()退出时变量超出范围时将调用析构函数,因此在注册后立即取消注册管理器。因此,只要将包加载到内存中,变量就必须存活。