如何包装具有参数的 C++ class 方法或在 C 中返回另一个 C++ class 的实例?
How to wrap C++ class method having a parameter or returning an instance of another C++ class in C?
我有一个 C++ class A
有方法,而其中一些使用另一个 C++ class B
的实例作为参数,有些是 returning 另一个 C++ 的实例 class C
。如何在 C 语言中正确包装 class A
及其所有方法?
我不认为我的问题是重复的,因为所有现有示例都显示了简单 C++ class 的 C 包装器(header 和源代码),其方法具有参数或 return 简单数据类型的值,如 int
、char*
等
class A {
public:
A(int param1);
int getValue();
private:
int value;
}
// method B::DoSomething() has a parameter of type (class) "A"
class B {
public:
void DoSomething(A param1);
}
// method C::SetSomething() returns an instance of class "A"
class C {
public:
A SetSomething(int value);
}
我知道如何为 class A
编写 C-language 包装器及其方法:使用 extern "C" { ... }
构造。
但是如何为 classes B
和 C
以及他们的方法做到这一点?
我建议将 struct B
和 struct C
转换为函数,因为它们没有成员:
void B_DoSomething(A * p_param)
{
//...
}
A C_SetSomething(int value)
{
A variable;
variable.value = value;
return variable;
}
提醒一下,您应该更喜欢在 C 语言中通过指针传递结构。否则编译器会生成副本(除非编译器可以优化)。
在几乎所有情况下,您不能。
仅当 struct
是 POD 时,这意味着它是普通的标准布局类型,并且没有非 POD 本身的非静态成员。
这基本上意味着您只能使用没有额外行为的数据块结构,并且 C "understands" 与 C++ 一样。
原因很简单:C 不了解 C++ 语义。例如,如果您的 class 有一个析构函数,谁来 运行 它?或者,如果您的 class 运行 复制了一些代码,C 如何知道它?
您有两个选择:
只分享那些类型。如果您不确定某物是否是 POD,请断言它(在 C++ 中):
static_assert(std::is_pod_v<T>);
保留你的 classes,但将不透明的指针传递给 C。因为你只是传递指针,C 不会对它们做任何事情。
请注意,您的示例 classes B
和 C
是 而不是 PODs,因此您不能这样做那些。
通用方法是为每个 C++ 创建一个包装器 class 和一个方法来生成指向这些包装器的指针,另一个方法用于删除它们。
extern "C" {
struct WA{
void* self;
};
struct WA* new_A( int p1 ){
WA* wa = new WA;
wa->self = new A( p1 );
return wa;
}
void delete_A( WA* wa ){
delete static_cast<A*>( wa->self );
delete wa;
}
}
然后将每个 class 的每个方法转换为一个函数,该函数将结构指针作为第一个参数。 A::getValue
变为
int A_getValue( WA* wa) {
return static_cast<A*>( wa->self )->getValue();
}
实例可以通过指针传入,所以B::DoSomething
变成
void B_DoSomething( WB *wb, WA *param1){
static_cast<B*>( wb->self )->DoSomething( *static_cast<A*>( param1->self ) );
}
同样,您可以通过指针 return 个实例。 C::SetSomething
然后变成
struct WA* C_SetSomething( WC* wc, int value ){
A a = static_cast<C*>( wc->self )->SetSomething( value );
return new_A( a.getValue() );
}
您需要非常小心地管理 C 代码中的内存。请参阅工作示例 here.
我有一个 C++ class A
有方法,而其中一些使用另一个 C++ class B
的实例作为参数,有些是 returning 另一个 C++ 的实例 class C
。如何在 C 语言中正确包装 class A
及其所有方法?
我不认为我的问题是重复的,因为所有现有示例都显示了简单 C++ class 的 C 包装器(header 和源代码),其方法具有参数或 return 简单数据类型的值,如 int
、char*
等
class A {
public:
A(int param1);
int getValue();
private:
int value;
}
// method B::DoSomething() has a parameter of type (class) "A"
class B {
public:
void DoSomething(A param1);
}
// method C::SetSomething() returns an instance of class "A"
class C {
public:
A SetSomething(int value);
}
我知道如何为 class A
编写 C-language 包装器及其方法:使用 extern "C" { ... }
构造。
但是如何为 classes B
和 C
以及他们的方法做到这一点?
我建议将 struct B
和 struct C
转换为函数,因为它们没有成员:
void B_DoSomething(A * p_param)
{
//...
}
A C_SetSomething(int value)
{
A variable;
variable.value = value;
return variable;
}
提醒一下,您应该更喜欢在 C 语言中通过指针传递结构。否则编译器会生成副本(除非编译器可以优化)。
在几乎所有情况下,您不能。
仅当 struct
是 POD 时,这意味着它是普通的标准布局类型,并且没有非 POD 本身的非静态成员。
这基本上意味着您只能使用没有额外行为的数据块结构,并且 C "understands" 与 C++ 一样。
原因很简单:C 不了解 C++ 语义。例如,如果您的 class 有一个析构函数,谁来 运行 它?或者,如果您的 class 运行 复制了一些代码,C 如何知道它?
您有两个选择:
只分享那些类型。如果您不确定某物是否是 POD,请断言它(在 C++ 中):
static_assert(std::is_pod_v<T>);
保留你的 classes,但将不透明的指针传递给 C。因为你只是传递指针,C 不会对它们做任何事情。
请注意,您的示例 classes B
和 C
是 而不是 PODs,因此您不能这样做那些。
通用方法是为每个 C++ 创建一个包装器 class 和一个方法来生成指向这些包装器的指针,另一个方法用于删除它们。
extern "C" {
struct WA{
void* self;
};
struct WA* new_A( int p1 ){
WA* wa = new WA;
wa->self = new A( p1 );
return wa;
}
void delete_A( WA* wa ){
delete static_cast<A*>( wa->self );
delete wa;
}
}
然后将每个 class 的每个方法转换为一个函数,该函数将结构指针作为第一个参数。 A::getValue
变为
int A_getValue( WA* wa) {
return static_cast<A*>( wa->self )->getValue();
}
实例可以通过指针传入,所以B::DoSomething
变成
void B_DoSomething( WB *wb, WA *param1){
static_cast<B*>( wb->self )->DoSomething( *static_cast<A*>( param1->self ) );
}
同样,您可以通过指针 return 个实例。 C::SetSomething
然后变成
struct WA* C_SetSomething( WC* wc, int value ){
A a = static_cast<C*>( wc->self )->SetSomething( value );
return new_A( a.getValue() );
}
您需要非常小心地管理 C 代码中的内存。请参阅工作示例 here.