无法在 BPL 中找到未解析的外部/过程入口点

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

我在一个继承自 TFileStream 的现有项目中有一个名为 TTextStream 的 class。 它有一组重载的 operator<<operator>> 函数作为成员函数。

class PACKAGE TTextStream : public TFileStream

大多数建议反而说您应该为这些运算符编写外部函数,并让他们成为所讨论的 class 的朋友,以便能够访问私有和受保护的成员。

因此,作为检查和清理代码的一部分,我这样做了。

并添加了函数示例

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

然后像往常一样在 .cpp 中执行。

然后在 TTextStream class 我添加了

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

该项目生成了一个 C++ Builder 程序包 (BPL),我们称它为 Foo.bpl。它编译得很好,然后我继续编译下一个 BPL 包,Bar.bpl,它使用来自 Foo.bpl 的功能.

所有这些 BPL 都输出到 "default" 文件夹,C:\Users\Public\Documents\Embarcadero\Studio。0\BLP

Foo.bpi 添加在 RequiresBar.bpl 项目。

构建后我得到了

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

如果我尝试使用 Foo.lib 静态地 link,它工作正常。经过一番挖掘后,我得出的结论是函数没有正确导出到 Foo.bpl.

据我所知,我必须为此使用 PACKAGE 宏,所以我将其添加到 .h 文件的定义中以及 .cpp 文件中的实现。

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

我重新编译 Foo.bpl,然后我编译 Bar.bpl 现在编译 link 很好。但是 Bar.bpl 是一个运行时和设计时包,当我在 IDE 中安装它时,会弹出一个 Windows 消息对话框,基本上与之前相同的消息。

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

所以好像是抱怨没有找到一个函数,那个好像是在Foo.bpl中导出在Bar.bpl[=中93=]?

不太确定我错过了什么。 TDUMP 似乎显示它实际上正在导出。

C:\Users\Public\Documents\Embarcadero\Studio.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()

或不进行解压缩

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='@$xpTTextStream'
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'

我还用其他调用约定进行了测试以排除这种情况。

作为二次测试我还创建了一个小测试用例。

一个生成 bpl 的项目,其单元 (functions.h/functions.cpp) 添加了一个函数

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

PACKAGE int add(int a, int b)

#endif

这只是将两个数字相加,并在 .cpp 文件中实现。编译并 linkk BPL。

然后我创建了一个控制台应用程序,需要有问题的 bpl,包含带有函数定义的头文件 (functions.h),编译但失败 linking 出现同样的错误。所以我可能遗漏了一些明显的小东西...

所有这些都是使用 RAD Studio 10.3.2not 使用 classic 编译器。

经过运行我进了这几次终于找到了一个好像"fix"的方法吧。 几个 BPL 项目,其中一些包含 IDE 组件,当我更改名称空间或其他内容时,拒绝安装并显示 "procedure entry point" 消息。函数已正确导出到 BPL,最终使其能够安装新版本组件 BPL 的是

  • 从 IDE
  • 中卸载组件
  • 构建 BPL 项目

在此之后安装出现错误,改为

  • 关闭 IDE
  • 开始 IDE 备份
  • 再次加载项目
  • 安装组件

我不知道为什么会这样,但现在它在 5 个项目中都运行良好。我猜某些缓存或其他东西对我来说很糟糕。或者可能首先卸载的旧 BPL 实际上并没有完全删除。

如果有人知道发生了什么,我很乐意提供信息。