我使用以下命令从 sqlite3.c 和 BCC 55 编译了 SQLite3 数据库引擎:
bcc32.exe -jb -O2 -w- -K -c -6 -u- sqlite3.c
生成了正确的 sqlite3.obj 文件。但是一旦我尝试将它链接到我的 Delphi 应用程序中,如下所示:
unit unt_SQLite3;
interface
uses
Windows;
implementation
{$LINK 'sqlite3.obj'}
end.
我收到以下错误:
[DCC Error] E2065 Unsatisfied forward or external declaration: '__ftol'
[DCC Error] E2065 Unsatisfied forward or external declaration: '__lldiv'
[DCC Error] E2065 Unsatisfied forward or external declaration: '__llmod'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_localtime'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_strncmp'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_memset'
[DCC Error] E2065 Unsatisfied forward or external declaration: '__llmul'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_malloc'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_free'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_realloc'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_memcpy'
[DCC Error] E2065 Unsatisfied forward or external declaration: '__llumod'
[DCC Error] E2065 Unsatisfied forward or external declaration: '__lludiv'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_memmove'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_memcmp'
[DCC Error] E2065 Unsatisfied forward or external declaration: '__llshl'
[DCC Error] E2065 Unsatisfied forward or external declaration: '__llshr'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_atol'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_strlen'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_qsort'
[DCC Error] E2065 Unsatisfied forward or external declaration: '__llushr'
[DCC Error] E2065 Unsatisfied forward or external declaration: '__turboFloat'
为什么需要在纯 pascal(或 asm)中实现 Borland C++ 运行时函数?
那些不能直接链接到 obj 中吗?
其中一些已经在 System.pas 中实现,但编译器仍然抱怨?
执行此 mysqlf 而不是使用 SynSQLite3 或 DIXml 的原因如下:
-
SynSQLite3 支持 3.7.8(我没有看到最新的 3.7.9)
-
SynSQLite3 缺少一些声明,如 sqlite3_trace、sqlite_open_v2 等。
-
在随后的 20 000 个步骤操作中,SynSQLite2 比 DIXml 2.4.0 慢约 18 倍
在
DISQLite3已付费
DISQLite 2.4.0 速度快,可在 260 毫秒内执行 20000 步操作,但不支持 DXE2
-
DISQLite 3.0。 0 和 3.1.0 确实支持 DXE2,但速度比 DXE2 慢 8 倍左右2.4.0
我是一个很好奇的人,总是尝试尽可能接近金属的代码。< /p>
-
向 SynSQLite3 和 DISQLite3 开发人员致敬 - 迄今为止所做的工作非常出色
最终我选择了 SynSQLite3,因为:
-
它是开源的
它有很好的文档记录
我学会了如何自己重新编译sqlite3.obj只留下我需要的功能所需的编译开关
我可以链接更新的 3.7.9 版本
通过微调的最新 3.7.9 obj,我实现了 DISQLite3 的速度
DISQLite3 的家伙在他的网站上甚至没有可以写信的电子邮件地址(只是一个邮件列表),SynSQLite3 的家伙在同一时间以 SO 回复。当选择一个库而不是另一个库时,这是有意义的。性能和价格并不是一切。

PS 我的 sqlite3.obj 暂时可供下载和测试 此处
I have compiled SQLIte3 database engine from sqlite3.c with BCC 55 using the following command:
bcc32.exe -jb -O2 -w- -K -c -6 -u- sqlite3.c
The proper sqlite3.obj file was generated. But once I try to link it in my Delphi application like this:
unit unt_SQLite3;
interface
uses
Windows;
implementation
{$LINK 'sqlite3.obj'}
end.
I get the following errors:
[DCC Error] E2065 Unsatisfied forward or external declaration: '__ftol'
[DCC Error] E2065 Unsatisfied forward or external declaration: '__lldiv'
[DCC Error] E2065 Unsatisfied forward or external declaration: '__llmod'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_localtime'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_strncmp'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_memset'
[DCC Error] E2065 Unsatisfied forward or external declaration: '__llmul'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_malloc'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_free'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_realloc'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_memcpy'
[DCC Error] E2065 Unsatisfied forward or external declaration: '__llumod'
[DCC Error] E2065 Unsatisfied forward or external declaration: '__lludiv'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_memmove'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_memcmp'
[DCC Error] E2065 Unsatisfied forward or external declaration: '__llshl'
[DCC Error] E2065 Unsatisfied forward or external declaration: '__llshr'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_atol'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_strlen'
[DCC Error] E2065 Unsatisfied forward or external declaration: '_qsort'
[DCC Error] E2065 Unsatisfied forward or external declaration: '__llushr'
[DCC Error] E2065 Unsatisfied forward or external declaration: '__turboFloat'
Why is needed to implement the Borland C++ runtime functions in pure pascal(or asm)?
Can't those linked in the obj directly?
Some of them are already implemented in System.pas but yet the compiler complains?
The rational behind doing this mysqlf instead of using SynSQLite3 or DIXml is the following:
-
SynSQLite3 supports 3.7.8 (I do not see the latest 3.7.9)
-
SynSQLite3 misses some declarations like sqlite3_trace, sqlite_open_v2, etc.
-
SynSQLite2 is around 18 times slower than DIXml 2.4.0 in consequent 20 000 step operations
-
DISQLite3 is paid
-
DISQLite 2.4.0 is fast does 20000 step operations in 260ms but does not support DXE2
-
DISQLite 3.0.0 and 3.1.0 do support DXE2 but are around 8 times slower than 2.4.0
-
I am very curious guy and always try to code as close to the metal as possible.
-
Kudos to SynSQLite3 and DISQLite3 developers - really good work doen so far
Eventually I ended up choosing SynSQLite3 because:
-
It is open source
-
It is very well documented
-
I learned how to recompile sqlite3.obj myself and leave just the needed compilation switches for the features I need
-
I can have the updated 3.7.9 version linked
-
With the fine tuned latest 3.7.9 obj I achieved the speed of DISQLite3
-
The DISQLite3 guy does not have even an email address on his site to write to (just a mailing list), where the SynSQLite3 guys reply in SO on the same hour. This makes sense when choosing one lib over another. Performance and price is not everything.

P.S. My sqlite3.obj is temporaly available for download and test here
发布评论
评论(2)
看看我们的开源库。它实现了 sqlite3.obj 的静态链接,并使用最新版本的 SQLite3 官方代码进行维护(和功能 - 例如,它是唯一允许扩展使用 SQLite3 虚拟表的框架)。你有一个包装纸。但还不止于此。
以下是我们如何将源代码编译为 .obj(一个包含 FTS3,另一个不包含 FTS3):
然后看一下 SynSQLite3.pas 单元。它包含一些所需外部文件的纯 pascal 或 asm 版本。
例如:
您将在本单元中发现不仅仅是 SQLite3 的静态链接。请注意,即使我们的 mORMot ORM 客户端-服务器框架使用它,该 ORM 也不是使用 SQLite3 类所必需的。请参阅本文了解更多详细信息。
如果您迷失在我们的源代码存储库中(使用伟大的 FOSSIL 项目),阅读此内容。
Take a look at our Open Source libraries. It implements static linking of sqlite3.obj, and is maintained with the latest version of SQLite3 official code (and features - it is the only framework allowing extended use of the SQLite3 Virtual Tables, for instance). You've got a wrapper. But more than that.
Here is how we compile the source into the .obj (one inclusing FTS3, the other without it):
Then take a look at the SynSQLite3.pas unit. It contains some pure pascal or asm version of the needed external files.
For instance:
You'll find in this unit much more than just a static linking of SQLite3. Note that even if it is used by our mORMot ORM Client-Server framework, this ORM is not required to use the SQLite3 classes. See this article for additional details.
If you are lost into our source code repository (using the great FOSSIL project), read this.
更新:按照 Arnaud 的建议,使用
SynSQLite3.pas
效果会更好。但是,我将这个答案留在这里,因为它说明了一些可用于解决静态链接时缺少的依赖项的技巧。这里发生的情况是 .obj 文件依赖于您需要提供的各种 C 运行时函数。
首先要做的是将
crtl
添加到包含$LINK
指令的单元的uses
子句中。crtl
单元包含许多 C 运行时库函数的实现,并且正是为此目的而设计的。但是,当您执行此操作时,虽然解决了一些缺少的依赖项,但还会出现更多依赖项。
其中许多只是 Windows API 函数,可以通过将
Windows
添加到 use 子句来轻松解决。此时,您将面临以下问题:
要解决这些问题,您需要执行以下任一操作:
$LINK
的同一单元中实现 Delphi 代码中缺少的依赖项。我实际上不确定这些函数的作用,因此您还有更多工作要做。我的猜测是这些函数是 64 位整数算术例程。您可以通过编写 C 的短位来执行各种 64 位算术运算来对此进行逆向工程。然后使用 bcc32 进行编译并查看输出为
asm
。据推测,bcc32
具有发出asm
的能力。或者您可以链接到 Delphi 单元并查看上述哪些函数对应于您在 C 代码中使用的操作。您可以从
msvcrt.dll
中提取localtime
,这始终是缺少 C 运行时函数的有用后备选项。事实上,这就是crtl
单元当前实现的作用,因此如果您要使用crtl
,您也可以获取localtime
同样的方式。借用 Arnaud 的一些代码,以下单元可以成功编译:
请注意,您不需要为任何这些函数提供参数列表、调用约定等,因为我们在这里没有实现它们。在每种情况下,代码只是简单地委托实现。
但是,这仍然缺少声明 sqlite3 函数的代码。更重要的是,我什至没有尝试测试它是否有效。成功编译只是第一步。
如果您想使用静态链接,我强烈建议您使用 Arnaud 指导您使用的代码。这段代码显然已经进行了大量的使用和测试,您也可以从中受益。
静态链接便于部署,但针对 DLL 的动态链接更容易实现。
Update: You will be far better off with
SynSQLite3.pas
as suggested by Arnaud. However, I am leaving this answer here since it illustrates some of the tricks that can be used to resolve missing dependencies when static linking.What is happening here is that the .obj file depends on various C runtime functions which need to be provided by you.
The first thing to do is to add
crtl
to theuses
clause of the unit which contains the$LINK
directive. Thecrtl
unit contains implementations of a number of the C runtime library functions and is designed for just this purpose.However, when you do this, whilst some missing dependencies are resolved, lots more appear.
Many of these are simply Windows API functions and can easily be resolved by adding
Windows
to your uses clause.At this point you are left with the following:
To resolve these you need to either:
$LINK
.I'm not actually sure what these functions do so you've got a bit more work ahead of you. My guess is that these functions are 64 bit integer arithmetic routines. You can probably reverse engineer this by writing short bits of C to perform various 64 bit arithmetic operations. Then compile with bcc32 and look at the output as
asm
. Presumablybcc32
has the capability to emitasm
. Or your could just link to a Delphi unit and see which of the above functions corresponds to the operations you used in your C code.You could pull
localtime
out ofmsvcrt.dll
, always a useful fall-back option for missing C runtime functions. In fact, that's what the current implementation of thecrtl
unit does, so if you are going to usecrtl
you may as well getlocaltime
the same way.Borrowing some code from Arnaud, the following unit compiles successfully:
Note that you don't need to provide parameter list, calling convention etc. for any of these functions since we are not implementing them here. In each case the code simply delegates the implementation.
However, this is still missing the code to declare the sqlite3 functions. What's more, I've not even attempted to test whether or not it works. Successful compilation is only the first step.
I strongly recommend that you use the code that Arnaud directs you towards if you wish to use static linking. This code clearly has had much use and testing and you may as well benefit from that.
Static linking makes for convenient deployment, but dynamic linking against a DLL is much simpler to achieve.