我在继承自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.bpl的Foo.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完成的,而不是使用经典编译器。