具有 C 链接和C++实现的不透明结构
Opaque struct with C linkage & C++ implementation
说我想要一个带有C链接的结构foo
。我将在C风格的标头文件(FOO.H)中声明:
struct foo;
typedef struct foo foo;
,但我想在foo
的实现中使用C 。说我希望foo
包含std::vector<int>
。由于C代码无法访问foo
的字段,因此我不明白为什么编译器(或语言标准)应该禁止这一点。但是我该怎么办?我可以在这样的foo.cc中将extern "C"
放在foo
的实现周围吗?
extern "C" {
struct foo {
....
std::vector<int> bar;
}
}
我最终在c下填充了c ...这是它的一般要旨。(顺便说一句,让C 例外放弃C堆栈可能会导致C代码不知道这些事情的问题...因此建议在C 接口函数中执行一些catch(...)
块。)
lib.h :一个标头文件,该文件声明了一些函数,无论是否编译为C还是C
#pragma once
#if defined(__cplusplus)
extern "C" {
#endif
/* Looks like a typical C library interface */
struct c_class;
struct c_class *do_init();
void do_add(struct c_class *tgt, int a);
int do_get_size(const struct c_class *tgt);
void do_cleanup(struct c_class *tgt);
#if defined(__cplusplus)
}
#endif
lib.cpp :c 库带有几个函数,用C调用convention
#include "lib.h"
#include <iostream>
#include <vector>
#include <cstdlib>
class Foo
{
std::vector<int> m_vec;
public:
Foo() : m_vec() {}
virtual ~Foo() {}
void add(int a) {
m_vec.push_back(a);
}
int getSize() {
return m_vec.size();
}
};
/* Exposed C interface with C++ insides */
extern "C" {
struct c_class
{
Foo *guts;
};
struct c_class *do_init()
{
struct c_class *obj = static_cast<c_class*>(malloc(sizeof(struct c_class)));
obj->guts = new Foo();
return obj;
}
void do_add(struct c_class *tgt, int a) {
tgt->guts->add(a);
}
int do_get_size(const struct c_class *tgt) {
return tgt->guts->getSize();
}
void do_cleanup(struct c_class *tgt) {
delete tgt->guts;
free(tgt);
}
}
main.c :使用从lib
导出的c调用约定功能的C程序#include <stdio.h>
#include "lib.h"
int main(int argc, char *argv[])
{
int i;
struct c_class *obj;
obj = do_init();
for(i = 0; i< 100; i++)
{
do_add(obj, i);
}
printf("Size: %dn", do_get_size(obj));
do_cleanup(obj);
}
makefile :将C构建为C的Makefile,而C 为C ,然后使用C 编译器进行链接
CXXFLAGS ?= -Wall -Werror -pedantic
CFLAGS ?= -Wall -Werror -pedantic
.PHONY: all
all : test
test: lib.o main.o
$(CXX) $(CXXFLAGS) -o test lib.o main.o
lib.o: lib.cpp lib.h
$(CXX) $(CXXFLAGS) -c $< -o $@
main.o: main.c lib.h
$(CC) $(CFLAGS) -c $< -o $@
clean:
-rm lib.o main.o test
输出:
$ make
g++ -Wall -Werror -pedantic -c lib.cpp -o lib.o
cc -Wall -Werror -pedantic -c main.c -o main.o
g++ -Wall -Werror -pedantic -o test lib.o main.o
$ ./test
Size: 100
只要结构的内容是pod(纯旧数据),c和c 之间的结构是兼容的。如果您在其中添加非pod,例如您的向量,它不再与C兼容,并且与典型的C函数(如memset
或memcpy
)一起使用时会导致不确定的行为。非POD成员导致结构的另一个内存布局,它在其开始时获得了一个虚拟表以支持继承。
struct本身只是一种类型,换句话说,句法糖不仅仅是编译为结构,而是记忆和指针中的几个字节。因此,它没有任何特定语言的链接。字节的含义由编译时的编译器定义,并在其中创建了对它们的引用。因此,它的布局取决于您使用的语言。
回答您的问题时,std ::向量实现包含某些字段,这些字段是结构布局的一部分。C 理解它们,因为它了解模板和所有其他面向对象的东西,因此" C"首先会在模板上以及其他C s扼流。因此,如果您使用非POD数据,则结构定义不兼容。
如果您使用POD,标准" C"数据类型,没有成员功能,并且没有位字段,则应在定义上全部设置和兼容。这意味着两个编译器都将编译结构,并且布局将相似,因此您可以保存/还原其跨语言。
如果您只是在谈论通过" C"代码将指针传递给C 结构,那么无论如何都应该设置。您可以使用铸件来以标准方式进行"无效*"。
- 如何创建子窗口是透明的,父窗口是不透明的?
- 从静态库使用时隐藏不透明结构的内容
- 在 C++ 中使用枚举而不是结构进行标记调度
- 成员引用基类型不是结构或联合
- C/C++intellisense 0.26.1不显示结构成员列表
- 对于指向C++类的不透明C指针,正确的typedef是什么
- 您自己的类型的结构化绑定,不是结构或元组(通过公共成员函数)
- for 循环说 - 错误 成员引用基类型"int [13]"不是结构或联合
- 成员引用基类型 'double [10]' 不是结构或联合
- 使用 pybind11 混合类型转换和不透明类型
- 继承依赖类型定义而不使用结构
- 处理 pybind11 中的不透明指针
- 错误:成员引用基类型"uint32_t"(也称为"无符号 INT")不是结构或联合
- Pybind11在不透明载体的不透明载体上访问
- 我不知道结构和指针的这种用法
- 具有 C 链接和C++实现的不透明结构
- unique_ptr到不透明结构?(C++)
- 如何使用模板化C++结构定义 C 向前声明的不透明结构
- 如果使用未命名结构体或未定义标记实现不透明指针
- 指向具有模板成员的结构体的不透明指针