qt4中如何调用C函数

来源:互联网 发布:电脑淘宝微淘在哪 编辑:程序博客网 时间:2024/05/18 03:40

      qt默认的编程语言为C++语言。如果你用qt编译.c文件,会出现找不到C语言的默认头文件等错误(如:stdio.h等)。qt中不支持 extern "C"{}的这种写法,我前几天有一个C程序需要移植到Qt的工程中,本希望直接

extern "C"

就ok了,但发现qt4居然不支持这种写法。我的程序中用到了好几个linux系统头文件,是向串口发指令之类的程序,程序中用到了互斥锁并创建了一个线程。如果再用qt语言来写一遍的话我会挂掉的,所以没有办法,在网上找了半天,终于找到解决方法。 将.c文件编译为函数库的方式在qt下调用,这种方法貌似行得通,我就开始行动了。 下面的内容讲得比较多,比较全,比较适合初学者,是我在网上down的,给出了原网站的链接,最后给出了一个程序。经过自己整理好归纳如下: 

需要说明的是:使用gcc可以将程序编译成动态库或者静态库的形式,它们在程序中的调用的方式也不尽相同,给出的程序中调用的是动态连接库。编译成动态的还是静态的根据自己的需要进行。如果原C程序编译的时候需要gcc的额外选项(如 gcc -lpthread -o hello hello.c)等,建议采用动态的形式。     

1.什么是静态连接库,什么是动态链接库 

      静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了。但是若使用 DLL,该 DLL 不必被包含在最终 EXE 文件中,EXE 文件执行时可以“动态”地引用和卸载这个与 EXE 独立的 DLL 文件。静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。在windows和linux上都是相同的,只不过文件的格式不同而已。 

2.gcc生成静态库和动态库 

第1步:编辑得到举例的程序--hello.h、hello.c和main.c; 

第2步:将hello.c编译成.o文件; 

无论静态库,还是动态库,都是由.o文件创建的。因此,我们必须将源程序hello.c通过gcc先编译成.o文件。 

在系统提示符下键入以下命令得到hello.o文件。

 # gcc -c hello.c 

第3步:由.o文件创建静态库; 
静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将创建的静态库名为myhello,则静态库文件名就是libmyhello.a。在创建和使用静态库时,需要注意这点。创建静态库用ar命令。 

在系统提示符下键入以下命令将创建静态库文件libmyhello.a。

 # ar crv libmyhello.a hello.o 

第4步:在程序中使用静态库; 

静态库制作完了,如何使用它内部的函数呢?只需要在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明静态库名,gcc将会从静态库中将公用函数连接到目标文件中。注意,gcc会在静态库名前加上前缀lib,然后追加扩展名.a得到的静态库文件名来查找静态库文件。 

在程序3:main.c中,我们包含了静态库的头文件hello.h,然后在主程序main中直接调用公用函数hello。下面先生成目标程序hello,然后运行hello程序看看结果如何。

 (# gcc -o hello main.c -L. -lmyhello??) #gcc main.c libmyhello.a -o main # ./hello 

第5步:由.o文件创建动态库文件; 
动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀lib,但其文件扩展名为.so。例如:我们将创建的动态库名为myhello,则动态库文件名就是libmyhello.so。用gcc来创建动态库。 

在系统提示符下键入以下命令得到动态库文件libmyhello.so。

 # gcc -shared -fPCI -o libmyhello.so hello.o

 第6步:在程序中使用动态库; 

在程序中使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明动态库名进行编译。我们先运行gcc命令生成目标文件,再运行它看看结果。

 # gcc -o hello main.c -L. -lmyhello # ./hello 


./hello: error while loading shared libraries: libmyhello.so: cannot open shar ed object file: No such file or directory 

哦!出错了。快看看错误提示,原来是找不到动态库文件libmyhello.so。程序在运行时,会在/usr/lib和/lib等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提示类似上述错误而终止程序运行。

我们将文件libmyhello.so复制到目录/usr/lib中,再试试。 

# mv libmyhello.so /usr/lib # ./hello Hello everyone! 

成功了。这也进一步说明了动态库在程序运行时是需要的。 编译参数解析 
最主要的是GCC命令行的一个选项: 

-shared 该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件 l -fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。 
l -L.:表示要连接的库在当前目录中 
l -ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称 
l LD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。 
l 当然如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用 /sbin/ldconfig来达到同样的目的,不过如果没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。 
调用动态库的时候有几个问题会经常碰到,有时,明明已经将库的头文件所在目录 通过 “-I” include进来了,库所在文件通过 “-L”参数引导,并指定了“-l”的库名,但通过ldd命令察看时,就是死活找不到你指定链接的so文件,这时你要作的就是通过修改 LD_LIBRARY_PATH或者/etc/ld.so.conf文件来指定动态库的目录。通常这样做就可以解决库无法链接的问题了
0 0