如何编译包含C源文件的C++源代码?

3

我正在尝试在C++程序中使用SQLite。由于我大多数时间都使用Java,因此我的C/C++知识有限。虽然我在大学里学过一些课程,但已经过了一段时间,我们从未涉及这方面的内容。SQLite是用C编写的。在编译程序时,您应该如何操作?(我在Windows平台上安装了MinGW,因此使用gcc和g++进行编译。)


3
一个程序如何包含另一个程序? - Nawaz
1
既然我们在谈技术,我很惊讶你没有问如何编译程序。我修改了标题以更准确地反映我的问题。 - Kenneth
4个回答

10

在 C++ 代码中,您可以通过

保护 C 头文件。
extern "C" { 

   // your includes here

}

这应该就是全部了——g++ 应该可以愉快地链接来自 gccg++ 的代码。在 C++ 系统头文件和许多库中也使用了 extern "C" ... 技巧,只需查看您的 g++ 安装或一些合适的开源项目所附带的头文件即可。这里有一个Boost 示例:

edd@max:~$ grep 'extern "C"' /usr/include/boost/date_time/*
/usr/include/boost/date_time/filetime_functions.hpp:    extern "C" {
/usr/include/boost/date_time/filetime_functions.hpp:    } // extern "C"
edd@max:~$ 

编辑: 感谢 delnan 的细心评论 --- 这是来自 sqlite3.h 头文件本身的内容:

/*
** Make sure we can call this stuff from C++.
*/
#ifdef __cplusplus
extern "C" {
#endif

所以当然已经处理好了。


注意:如果SQLite头文件已经包含了这个(以及#ifdef __cplusplus技巧,只有在被C++程序包含时才会执行此操作),我不会感到惊讶。 - user395760
我忘了提到一个好点:即使是 C 系统以及许多库头文件也有这个技巧。 - Dirk Eddelbuettel

3
C++通过使用extern "C"声明实现与C的兼容性。关于extern "C"的含义和为什么需要它,有一些很好的解释在这个SO问题中:Why do we need extern “C”{ #include } in C++?。几乎所有基于C的库,包括sqlite,在其头文件中包含extern "C"以提供自动的C++兼容性。
因此,SQLite将在您正常包含头文件和库的情况下(与C或C++库相同)无需任何特殊处理即可工作...
/* my_sqlite_program.cpp */
#include <sqlite3.h>

int main()
   {
   ...call sqlite functions...
   }

编译使用

g++ -Wall -Werror    my_sqlite_program.cpp  -lsqlite3 -o my_sqlite_program

“-lsqlite3” 是指包含的头文件还是其他文件? - Kenneth
1
这是一个不同的文件。要使用来自C或C++的库,您需要包含头文件sqlite3.h,其中描述了函数,以及库文件,其中提供了函数的实现。在g++命令行上提供-lsqlite3会导致您的程序链接到sqlite3的库实现文件。实际的库文件是/usr/lib/libsqlite3的某个版本,但gcc使用-lsqlite3作为指定它的速记方式。 - Brent Bradburn

2
针对SQLite这个数据库,其实并没有什么复杂的地方。如果你使用动态或静态库,只需包含其头文件并链接正确的lib文件即可。
如果你要完全将SQLite包含在你的应用程序中,你需要将所有源代码文件包含在项目中并构建它们,并根据需要包含头文件(尽管使用静态/动态库可能更好)。
如果你需要在编译为C++的文件中使用C代码,那么Dirk的答案是正确的,但对于SQLite来说这并不是必需的。

当我使用g++编译我的cpp文件时,我唯一得到的错误是“undefined reference to ...”错误,其中...部分是一个sqlite函数。我已经包含了sqlite3.h文件...不确定我做错了什么... - Kenneth
你说要包含头文件并链接到正确的库(对于静态或动态库),你能进一步解释一下吗? - Kenneth
我对g++不是特别熟悉,但您是否已经正确包含了所有内容,名称正确,并向链接器提供了必要的文件?至于我的评论,根据您想要设置SQLite的方式(如果您将其构建为共享模块/ dll或者您想要将其包含在内),您需要向链接器提供适当的库。 - ssube

1
你如何从C++源代码中调用C程序?通过使用编译器提供的链接规范(linkage specification)工具。该规范告诉编译器如何链接源代码。链接规范的格式如下:
extern "Language_Type" 
{ 

}

在您的情况下,您可以像这样包装您的SQLlite C函数

extern "C" 
{
    //SQLite function declarations
}

这应该能让你的程序正常工作,但是由于你试图从C++调用SQLite的C函数,SQLite已经提供了一些包装器来实现你想要的功能。请在SQLite官网上查看更多详细信息。此外,一些开源项目也提供了你所需的功能。请查看CppSQLite
希望对你有所帮助!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接