1

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

class PACKAGE TTextStream : public TFileStream

大多数建议相反,您应该为这些运算符编写外部函数,并使它们成为相关类的朋友,以便能够访问私有和受保护的成员。

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

并添加了功能示例

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

然后像往常一样在.cpp中实现。

然后在我添加的TTextStream类中

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

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

所有这些 BPL 都输出到“默认”文件夹C:\Users\Public\Documents\Embarcadero\Studio\20.0\BLP

Foo.bpi添加在Bar.bpl项目Requires下。

在建造时我得到了

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

如果我尝试与Foo.lib静态链接,它可以正常工作。经过一番挖掘,我得出结论,该函数没有正确导出到Foo.bpl

据我了解,我必须为此使用PACKAGE宏,因此我将其添加到.h文件中的定义和.cpp文件中的实现中。

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

我重新编译Foo.bpl,然后编译Bar.bpl,它现在可以正常编译和链接。但是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\20.0\BPL\Dcl\Bar.bpl

所以它似乎抱怨没有找到一个函数,这似乎是在Bar.bplFoo.bpl中导出的?

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

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()

或不拆线

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'

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

作为辅助测试,我还创建了一个小测试用例。

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

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

PACKAGE int add(int a, int b)

#endif

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

然后我创建了一个控制台应用程序,它需要有问题的 bpl,包含带有函数定义 (functions.h) 的头文件,编译并且链接失败并出现相同的错误。所以我可能错过了一些明显的小事......

所有这些都是使用RAD Studio 10.3.2完成的,而不是使用经典编译器。

4

1 回答 1

0

在遇到这种情况几次之后,我终于找到了一种似乎可以“修复”它的方法。例如,当我更改命名空间或其他内容时,其中一些包含 IDE 组件的 BPL 项目拒绝安装并显示消息“过程入口点”。函数已正确导出到 BPL,最终使它能够安装新版本的组件 BPL 的是

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

在此之后安装给出了错误,而不是

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

我不知道为什么会这样,但现在 5 个项目都运行良好。我猜一些缓存或某些东西让我搞砸了。或者,可能首先卸载的旧 BPL 实际上并没有完全删除。

如果有人知道发生了什么,我会很高兴获得这些信息。

于 2019-10-18T11:13:08.040 回答