有没有什么技巧可以告诉我如何在C程序和C++库之间传递指向结构体、双精度浮点数、函数等的指针,以及如何在它们之间来回传递?
假设您正在使用两个不同的库(静态或动态)进行编码(在Windows上为DLL,在Linux和其他* nix变体上为共享库),我最担心的问题如下:
它们使用相同的编译器进行编译。虽然如果所有C ++导出项都使用C样式命名约定导出,则这并非必需,但对于两个C ++模块之间的类实例之间的C ++到C ++调用而言,这是必需的。这是由于不同的编译器以不同的方式编译C ++导出内容。
不要将C ++类强制转换为C结构体。即使字段布局相同,它们在内部也不相同。如果C ++类具有任何虚成员,则C ++类具有“v表”;该v表允许调用继承或基类方法。
对于C到C或C ++到C ++以及C到C ++,也是如此。确保两者使用相同的字节对齐方式进行输出库。 您只能通过阅读编译器或开发环境文档来确定这一点。
不要混合malloc / free和new / delete。 更具体地说,不要使用new分配内存,并使用“free”释放内存,反之亦然。许多编译器和操作系统在两者之间处理内存管理的方式不同。
传递函数指针:只要它们作为“extern“C””暴露给/从C ++,这应该没问题。(您需要参考编译器文档来确定何时将头文件编译为C或C ++以保持其在一个文件中,或者您将需要每个项目中有两个相同函数声明的副本-我建议使用第一个方法)
传递双精度:这是C和C ++中的一种内置类型,并且应该以相同的方式处理。
如果必须与C函数共享C ++对象的实例,并在C代码中对其进行操作,请公开一组C导出的帮助程序函数,这些函数调用C ++对象上的适当方法。纯C代码无法正确地调用C ++对象上的方法。
伪代码示例:
// C++ 类
class foo {
public:
void DoIt();
};
// 导出帮助声明
extern "C" void call_doit(foo* pFoo);
extern "C" foo* allocate_foo();
extern "C" deallocate_foo(foo* pFoo);
// 实现
void call_doit(foo* pFoo)
{
pFoo->DoIt();
}
foo* allocate_foo()
{
return new foo();
}
void deallocate_foo(foo* pFoo)
{
delete pFoo;
}
// C语言消费端
void main()
{
foo* pFoo= allocate_foo();
call_doit(pFoo);
dealocate_foo(pFoo);
}
C和C++指针是相同的——指针基本上指向一块内存,从C/C++转换时不会改变。
您需要小心不要跨堆类型——例如,在一个库中分配并在可能具有另一个堆或使用另一个运行时版本的库中取消分配(反之亦然)。
您是否想询问有关按值传递或按引用传递的问题?提供更具体的问题可能会有所帮助。
extern "C"
来定义它们,以避免它们被混淆。 - psychotik