C++ 使用C++;来自C的对象
我想使用C/C++混合代码。我还需要从C代码访问C++对象成员变量。 它工作(至少在gcc中),我将指针传递到对象,并将其作为C++ 使用C++;来自C的对象,c++,c,object,C++,C,Object,我想使用C/C++混合代码。我还需要从C代码访问C++对象成员变量。 它工作(至少在gcc中),我将指针传递到对象,并将其作为结构处理 从C++开始: class MyData { ... }; 从C: struct MyData { ... }; (当然,我不会在最终的头文件中重复代码) 1,我不确定使用任何编译器都可以做到这一点。我有什么理由不相信这一点吗 2,如果MyData类具有虚拟成员函数,这将不起作用,但是指向第一个成员变量的指针可以解决问题。这是安全的,还是会给我带来麻
结构处理
从C++开始:
class MyData {
...
};
从C:
struct MyData {
...
};
(当然,我不会在最终的头文件中重复代码)
1,我不确定使用任何编译器都可以做到这一点。我有什么理由不相信这一点吗
2,如果MyData
类具有虚拟成员函数,这将不起作用,但是指向第一个成员变量的指针可以解决问题。这是安全的,还是会给我带来麻烦?编写一个在C和C++中都合法的类:
struct MyData {
int member;
};
您可以在两种语言中使用这个类/结构定义,并来回传递它的实例
如果类具有C++函数,如成员函数、基函数、非平凡成员等,那么只能在不透明指针中使用C,这将不允许你访问成员。
编写C和C++中都合法的类:
struct MyData {
int member;
};
您可以在两种语言中使用这个类/结构定义,并来回传递它的实例
如果类具有C++函数,如成员函数、基函数、非平凡成员等,那么只能在不透明指针中使用C,这将不允许你访问成员。
< P>第一个答案已经被建议定义一个“C”和C++中的合法的“胶类型”。然而,重要的是要强调,这是必要的,但还不够。更精确的答案是,您需要定义具有相同二进制布局的相同类型
澄清:
struct my_struct {
int a;
bool b;
};
根据my_struct
的对齐方式,可以有完全不同的二进制表示形式(当对齐方式为16位和32位时,my_struct
的大小是多少?)。在这种情况下,不仅成员很重要,而且成员之间的内容也很重要,即填充位
这就是为什么指向第一个成员的指针不足以拥有可移植代码的原因
最可移植的方法是定义一个更高级别的API,提取您正在做的事情的本质,并拥有可以通过简单类型(即int、chars、float)参数化的函数第一个答案已经提出定义一个“胶”类型,在C和C++中都是合法的。然而,重要的是要强调,这是必要的,但还不够。更精确的答案是,您需要定义具有相同二进制布局的相同类型
澄清:
struct my_struct {
int a;
bool b;
};
根据my_struct
的对齐方式,可以有完全不同的二进制表示形式(当对齐方式为16位和32位时,my_struct
的大小是多少?)。在这种情况下,不仅成员很重要,而且成员之间的内容也很重要,即填充位
这就是为什么指向第一个成员的指针不足以拥有可移植代码的原因
最可移植的方法是定义一个更高级别的API,提取您正在做的事情的本质,并拥有可以通过简单类型(即int、chars、float)参数化的函数 >经典的方法是,C++代码公开了C类函数来访问类的实例。并将这些函数标记为外部“C”
示例mydata.h
#ifndef HEADER_H
#define HEADER_H
#ifdef __cplusplus
class MyData
{
public:
MyData();
void SetX(int val);
int GetX();
private:
int _x;
};
#endif
typedef void* MYDATA;
#ifdef __cplusplus
extern "C" {
#endif
MYDATA MyData_new();
void MyData_delete(MYDATA md);
void MyData_SetX(MYDATA md, int x);
int MyData_GetX(MYDATA md);
#ifdef __cplusplus
}
#endif
#endif
然后在mydata.cpp
#include "mydata.h"
MyData::MyData() : _x(0)
{
}
int MyData::GetX()
{
return _x;
}
void MyData::SetX(int val)
{
_x = val;
}
extern "C" MYDATA MyData_new()
{
return new MyData();
}
extern "C" void MyData_Delete(MYDATA foo)
{
auto pFoo = reinterpret_cast<MyData*>(foo);
delete pFoo;
}
extern "C" void MyData_SetX(MYDATA foo, int x)
{
auto pFoo = reinterpret_cast<MyData*>(foo);
pFoo->SetX(x);
}
extern "C" int MyData_GetX(MYDATA foo)
{
auto pFoo = reinterpret_cast<MyData*>(foo);
return pFoo->GetX();
}
#包括“mydata.h”
MyData::MyData():x(0)
{
}
int MyData::GetX()
{
返回x;
}
void MyData::SetX(int val)
{
_x=val;
}
extern“C”MYDATA MYDATA_new()
{
返回新的MyData();
}
外部“C”无效MyData_删除(MyData foo)
{
自动pFoo=重新解释铸造(foo);
删除pFoo;
}
外部“C”无效MyData_SetX(MyData foo,int x)
{
自动pFoo=重新解释铸造(foo);
pFoo->SetX(x);
}
外部“C”int MyData_GetX(MyData foo)
{
自动pFoo=重新解释铸造(foo);
返回pFoo->GetX();
}
<>代码>经典的方法是C++代码公开C类函数来访问类的实例。并将这些函数标记为外部“C”
示例mydata.h
#ifndef HEADER_H
#define HEADER_H
#ifdef __cplusplus
class MyData
{
public:
MyData();
void SetX(int val);
int GetX();
private:
int _x;
};
#endif
typedef void* MYDATA;
#ifdef __cplusplus
extern "C" {
#endif
MYDATA MyData_new();
void MyData_delete(MYDATA md);
void MyData_SetX(MYDATA md, int x);
int MyData_GetX(MYDATA md);
#ifdef __cplusplus
}
#endif
#endif
然后在mydata.cpp
#include "mydata.h"
MyData::MyData() : _x(0)
{
}
int MyData::GetX()
{
return _x;
}
void MyData::SetX(int val)
{
_x = val;
}
extern "C" MYDATA MyData_new()
{
return new MyData();
}
extern "C" void MyData_Delete(MYDATA foo)
{
auto pFoo = reinterpret_cast<MyData*>(foo);
delete pFoo;
}
extern "C" void MyData_SetX(MYDATA foo, int x)
{
auto pFoo = reinterpret_cast<MyData*>(foo);
pFoo->SetX(x);
}
extern "C" int MyData_GetX(MYDATA foo)
{
auto pFoo = reinterpret_cast<MyData*>(foo);
return pFoo->GetX();
}
#包括“mydata.h”
MyData::MyData():x(0)
{
}
int MyData::GetX()
{
返回x;
}
void MyData::SetX(int val)
{
_x=val;
}
extern“C”MYDATA MYDATA_new()
{
返回新的MyData();
}
外部“C”无效MyData_删除(MyData foo)
{
自动pFoo=重新解释铸造(foo);
删除pFoo;
}
外部“C”无效MyData_SetX(MyData foo,int x)
{
自动pFoo=重新解释铸造(foo);
pFoo->SetX(x);
}
外部“C”int MyData_GetX(MyData foo)
{
自动pFoo=重新解释铸造(foo);
返回pFoo->GetX();
}
<>这是为C++代码编写一个C接口API。
我将使用一个单独的头文件和一个单独的.cpp文件来实现这一点。在头文件中定义一个API,它强< > < /强>包含C++头。这是新手犯的错误。此标头必须作为代码的C版本独立存在
我不会公开任何类型的struct
。如果必须,可以使用返回成员指针的函数。然后C代码可以直接读写指针。更好的方法是使用函数显式获取和设置成员值
您可以对对象类型使用void*
或struct
转发声明
然后构建C函数来构造、析构函数、复制和所有成员函数,这些函数将指向this
的指针作为参数。你不能称之为代码>代码< >代码>,因为这与C++冲突,所以使用<代码>自我>代码>或其他什么。构造函数和复制构造函数显然不接受此
,它们返回指向新对象的指针
将所有这些函数放在带有ifdef保护的extern“C”{}
块的头中
下面是我玩过的一个例子:
如何做到这一点