使用C库进行C++程序

joh*_*een 39 c c++ robotics

我正在尝试使用使用Qt制作的GUI来控制Dynamixel伺服.Dynamixel提供了一组C库来控制电机,而我知道GUI的唯一方法是Qt,它本质上是C++.是否可以以任何方式使用Qt C++代码中的Dynamixel C库?

And*_*ani 51

是的,C++可以使用C++编译器编译C,并且可以将C++与C链接.请确保您调用的任何C函数都使用C链接.这是我的封闭原型extern "C"

#ifdef __cplusplus
extern "C"{
#endif 

void c_function_prototype();

#ifdef __cplusplus
}
#endif
Run Code Online (Sandbox Code Playgroud)

BTW的标题可能已经这样做了.

  • 您可以通过指定 C 链接来使用 C++ 编译器编译大多数 C *声明*,如您所示,但一般 C 代码并非如此,除非它经过精心设计,或者您非常幸运。如果你尝试,你可能会遇到编译错误,但如果你没那么幸运,那么你可能会成功编译一个损坏的程序。 (2认同)

Jas*_*son 12

当然...... C代码一直都是从C++调用的.例如,大多数OS库是用C而不是C++编写的.因此,每当您从C++代码进行系统调用以执行移交给操作系统内核的任务时,这些都会通过C代码调用.

请确保在编译时包含正确的标题并链接有问题的C库.还记得extern "C"如果头文件尚未声明它们,则用于为C库函数指定C链接.请记住,某些库可能没有明确声明其功能extern "C",但可能使用了预处理器令牌.因此,在假设库编写者尚未将其库定义为具有C链接之前,您还需要检查它.

gcc可以使用-l交换机来链接自定义库.如果需要为库的位置指定自定义目录,可以使用该-L开关完成.例如:

g++ -std=c++11 my_code.cpp -lmy_library -L/custom_directory_path
Run Code Online (Sandbox Code Playgroud)

请注意,-l-L开关位于您正在编译的代码或目标文件之后,如果您的库类似于libjpglibrobotics等,lib则在将其附加到-l交换机时删除该部分名称.

  • 所有主要图书馆都已正确包装AFAIK.来自第三方供应商的自定义库(例如机器人制造商)可能没有.这取决于.我已经看到一些旧的商业代码没有这样包装. (4认同)

Mic*_*son 7

您可以使用C++中的C库...但是有一些警告.

使用第三方C库和C++时要注意的一件大事是错误处理.

一些C库使用setjmp/等设施longjmp进行错误处理.(卢阿是一个值得注意的例子).这意味着在错误堆栈上展开不会以正常方式发生,并且您可能会泄漏资源.类似于通常的C++ RAII风格的资源保护措施失败了.(这些调用比gotoC++代码更差).

也可以考虑例外.如果C++异常传播到C/C++边界,则应用程序可能会终止而不是传播异常.(取决于C库的编译方式和操作系统等.)(如果将C++函数作为回调传递给C库,可能会出现这种情况.)


小智 7

是.要使用C库函数,请在.cpp程序myprog.cpp中使用extern"C",如下所示

extern "C" {
    // C Function call
    cfunc();
}

int main()
{
    cfunc();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这个cfunc应该在c库中定义,如下所示

#include <stdio.h>

void cfunc()
{
   printf("This is from c library");
}
Run Code Online (Sandbox Code Playgroud)

然后,您需要为C库创建.o目标文件和.so共享对象文件,如下所示

$] gcc -c prog.c -o prog
$] gcc -shared -o libprog.so prog.o

$] export LD_LIBRARY_PATH=/path/to/clibrary:$LD_LIBRARY_PATH
$] g++ -L/path/to/clibrary myprog.cpp -o myprog.o -lprog
Run Code Online (Sandbox Code Playgroud)


ssg*_*reg 5

不要忘记extern "C"图书馆标题.在这里阅读 C的"外部"如何运作?