简体   繁体   中英

Unresolved external / procedure entry point could not be located in BPL

I have a class called TTextStream in an existing project that inherits from TFileStream . It had a set of overloaded operator<< and operator>> function as member functions.

class PACKAGE TTextStream : public TFileStream

Most recommendations instead say that you should write external functions for those operators and make them friends of the class in question to be able to access private and protected memebers.

So as part of going through and cleaning up the code I did this.

And example of a function added

TTextStream& __fastcall operator >>(TTextStream& ts, AnsiString& s);

The implementation is then in the .cpp as usual.

Then within the TTextStream class I added

friend TTextStream& __fastcall operator >>(TTextStream& ts, AnsiString& s);

The project produces a C++ Builder package (BPL) , let's call it Foo.bpl . It compiled fine and I then went on to compile the next BPL package, Bar.bpl , that uses functionality from Foo.bpl .

All these BPL's are outputed to the "default" folder, C:\Users\Public\Documents\Embarcadero\Studio\20.0\BLP

Foo.bpi is added under Requires in the Bar.bpl project.

Upon building I got

[ilink32 Error] Error: Unresolved external '__fastcall operator >>(TTextStream&, System::AnsiStringT<0>&)' referenced from BLABLABLA.OBJ

If I tried to link statically with Foo.lib instead it works fine. After some digging I come to the conclusion that the function hasn't been exported correctly to Foo.bpl .

As I understand it I have to use the PACKAGE macro for this so I add this to the definition in the .h file and the implementation in the .cpp file.

PACKAGE TTextStream& __fastcall operator <<(TTextStream& ts, const AnsiString& s);

I recompile Foo.bpl , I then compile Bar.bpl and it now compiles and links fine. But Bar.bpl is a runtime and design time package and when I go to install it in the IDE a Windows message dialog pops up with basically the same message as before.

The procedure entry point @$blsh$qr11TTextStreamrx27System@%AnsiStringT$us$i0$% could not be located in the dynamic library C:\Users\Public\Documents\Embarcadero\Studio\20.0\BPL\Dcl\Bar.bpl

So it seems to complain about not finding a function, that seems to be exported in Foo.bpl in Bar.bpl ?

Not quite sure what I'm missing. TDUMP seems to show it actually being exported.

C:\Users\Public\Documents\Embarcadero\Studio\20.0\Bpl>tdump -oiEXTDEF Foo.bpl | grep TTextStream
File STDIN:
    00050668  211 0000 __fastcall operator <<(TTextStream&, const char *)
    000505D8  210 0001 __fastcall operator <<(TTextStream&, System::WideString&)
    0005057C  209 0002 __fastcall operator <<(TTextStream&, System::AnsiStringT<0>&)
    00051350  213 0003 __fastcall operator >>(TTextStream&, System::WideString&)
    000506B0  212 0004 __fastcall operator >>(TTextStream&, System::AnsiStringT<0>&)
    00051D6C  218 0009 __tpdsc__ TTextStream
    00051D3C  217 00DB TTextStream::
    00051A18  216 00DC TTextStream::operator =(TTextStream&)
    00050150  207 00DD __fastcall TTextStream::TTextStream(System::AnsiStringT<0>&, unsigned short, TEOLMode)
    0005157C  215 00DE TTextStream::TTextStream(TTextStream&)
    000514F4  214 00DF __fastcall TTextStream::~TTextStream()
    0005051C  208 00E0 __fastcall TTextStream::WriteEOL()

or without de-mangling

EXPORT ord:0211='@$blsh$qr11TTextStreampxc'
EXPORT ord:0210='@$blsh$qr11TTextStreamrx17System@WideString'
EXPORT ord:0209='@$blsh$qr11TTextStreamrx27System@%AnsiStringT$us$i0$%'
EXPORT ord:0213='@$brsh$qr11TTextStreamr17System@WideString'
EXPORT ord:0212='@$brsh$qr11TTextStreamr27System@%AnsiStringT$us$i0$%'
EXPORT ord:0218='@$xp$11TTextStream'
EXPORT ord:0050='@TLangFormNode@SaveToASCII$qqrp11TTextStreamui'
EXPORT ord:0217='@TTextStream@'
EXPORT ord:0216='@TTextStream@$basg$qrx11TTextStream'
EXPORT ord:0207='@TTextStream@$bctr$qqrrx27System@%AnsiStringT$us$i0$%us8TEOLMode'
EXPORT ord:0215='@TTextStream@$bctr$qrx11TTextStream'
EXPORT ord:0214='@TTextStream@$bdtr$qqrv'
EXPORT ord:0208='@TTextStream@WriteEOL$qqrv'

I have also tested with other calling conventions to rule that out.

As a secondary test I also created a small test case.

A project producing a bpl with a Unit (functions.h/functions.cpp) added with a single function

#ifndef __MYFUNCS__
#define __MYFUNCS__
#pragma package(smart_init)

PACKAGE int add(int a, int b)

#endif

that just adds the two numbers together, with the implementation in the.cpp file. Compile and linkk the BPL.

Then I created a console app that required the bpl in question, included the header file with the function definition (functions.h), compile and it fails linking with the same error. So I'm probably missing some minor obvious thing...

All this is done using RAD Studio 10.3.2 and not using the classic compiler.

After running into this a few times I finally found a way that seems to "fix" it. Several BPL projects some of which contain IDE components refused to install with the message "procedure entry point" when I for instance changed a namespace or something. Functions were exported correctly to the BPL and what finally made it able to install the new version of the component BPL was

  • Uninstall component from IDE
  • Build the BPL project

Installing after this gave the error, instead

  • Shutdown the IDE
  • Start the IDE back up
  • Load the project again
  • Install the component

I have no idea why this works but it has worked fine for 5 projects now. I'm guessing some cache or something is messing up for me. Or perhaps the old BPL that is uninstalled first doesn't actually get removed entirely.

If anyone has any idea what is going on I would be happy for the info.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM