无法链接_sqlite3_unlock_notify函数问题的解决

目录

一、问题

二、解决方案

三、sqlite3_unlock_notify与_sqlite3_unlock_notify

1、__cdecl

2、_cdecl、_stdcall、__fastcall三者之间的区别

四、查看sqlite3.lib和sqlite3.dll

1、sqlite3.lib

2、sqlite3.dll


一、问题

编译odb的libodb-sqlite-2.4.0时,出现了无法链接_sqlite3_unlock_notify函数的问题。

二、解决方案

输入命令cl sqlite3.c -DSQLITE_ENABLE_UNLOCK_NOTIFY -DSQLITE_API=__declspec(dllexport) -link -dll -out:sqlite3.dll

三、sqlite3_unlock_notify与_sqlite3_unlock_notify

       出现了无法链接_sqlite3_unlock_notify, 为啥sqlite3_unlock_notify函数名前面要加_?这个就要从调用约定说了。

1、__cdecl

__cdecl的特点
__cdecl 是 C Declaration 的缩写,表示 C 和 C++ 默认的函数调用约定。是C/C++和MFCX的默认调用约定。

按从右至左的顺序压参数入栈、。
由调用者把参数弹出栈。切记:对于传送参数的内存栈是由调用者来维护的,返回值在EAX中。因此对于像printf这样可变参数的函数必须用这种约定。
编译器在编译的时候对这种调用规则的函数生成修饰名的时候,在输出函数名前加上一个下划线前缀,格式为_function。如函数int add(int a, int b)的修饰名是_add。
(1).为了验证参数是从右至左的顺序压栈的,我们可以看下面这段代码,Debug进行单步调试,可以看到我们的调用栈会先进入GetC(),再进入GetB(),最后进入GetA()。


(2).第二点“调用者把参数弹出栈”,这是编译器的工作,暂时没办法验证。要深入了解这部分,需要学习汇编语言相关的知识。

(3).函数的修饰名,这个可以通过对编译出的dll使用VS的”dumpbin /exports ProjectName.dll”命令进行查看(后面章节会进行详细介绍),或直接打开.obj文件查找对应的方法名(如搜索add)。

从代码和程序调试的层面考虑,参数的压栈顺序和栈的清理我们都不用太观注,因为这是编译器的决定的,我们改变不了。但第三点却常常困扰我们,因为如果不弄清楚这点,在多个库之间(如dll、lib、exe)相互调用、依赖时常常出出现莫名其妙的错误。这个我在后面章节会进行详细介绍。
 

2、_cdecl、_stdcall、__fastcall三者之间的区别

无法链接_sqlite3_unlock_notify函数问题的解决_第1张图片

四、查看sqlite3.lib和sqlite3.dll

1、sqlite3.lib

dumpbin /exports sqlite3.lib

无法链接_sqlite3_unlock_notify函数问题的解决_第2张图片

 无法链接_sqlite3_unlock_notify函数问题的解决_第3张图片

2、sqlite3.dll

dumpbin /exports sqlite3.dll

 无法链接_sqlite3_unlock_notify函数问题的解决_第4张图片

 无法链接_sqlite3_unlock_notify函数问题的解决_第5张图片

 参考:

带你玩转Visual Studio——调用约定__cdecl、__stdcall和__fastcall_luoweifu的博客-CSDN博客___cdecl __stdcall有一定C++开发经验的人一定对”__cdecl、__stdcall、__fastcall”肯定不陌生吧!但你真正理解了吗?是的,我曾在这采了无数个坑,栽了无数个跟头,终于忍无可忍要把它总结一下(虽然我已经有能力解决大部分这种问题了)!什么是调用约定 函数的调用约定,顾名思义就是对函数调用的一个约束和规定(规范),描述了函数参数是怎么传递和由谁清除堆栈的。它决定以下内容:(1)函数参数的压栈顺序,https://blog.csdn.net/luoweifu/article/details/52425733#commentBox

你可能感兴趣的:(数据库,c++,c++,sqlite3)