Registering a custom CodeInsight manager to C++Builder without initialization/finalization sections

北城余情 提交于 2019-12-11 07:13:42

问题


I'm trying to register a custom CodeInsight manager into C++Builder 10.1.2 Berlin.

Because there's nothing like Objects Pascal's initialization and finalization sections in C++, e.g.

var
  codeManagerIndex: Integer;

{...}

initialization
  codeManagerIndex := (BorlandIDEServices as IOTACodeInsightServices).AddCodeInsightManager(TMyCodeInsightManager.Create);

finalization
  (borlandIDEServices as IOTACodeInsightServices).RemoveCodeInsightManager(codeManagerIndex);
end.

I tried reproducing their behavior with a custom runner class with constructor/destructor:

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;
}

I can compile my simple implementation but when I try to install the package the following things are happening:

  • 1st try: Error message: Can't load package ... mypackage.bpl - A dynamic link library (DLL) initialization routine failed.

  • 2nd try: An exception (C0000005) occured during DllEntryPoint or DllMain in module: ... mypackage.bpl ... then the IDE crashes.

Is this a wrong way to register? What am I doing wrong here?

P.S. I get a [TLIB Warning] Warning: library was too large for page size, rebuilt with page size 32 warning when compiling, but I'm quite sure that this can't be the reason for my errors. (?)


回答1:


there's nothing like Objects Pascal's initialization and finalization sections in C++

Actually, there is. In C++Builder, you can use #pragma startup and #pragma exit to execute user-defined functions:

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;
}

Alternatively, since you ready declared a class to handle your registration, you can simply move your class variable into global static memory so its constructor runs at startup and destructor runs at 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;
}

Declaring the class variable inside of _libmain() is useless since the destructor will be called when the variable goes out of scope when _libmain() exits, thus unregistering the manager immediately after registering it. So the variable has to survive for as long as the package is loaded in memory.



来源:https://stackoverflow.com/questions/41922887/registering-a-custom-codeinsight-manager-to-cbuilder-without-initialization-fi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!