如何使用C++;C代码? 我试图为C++第三方库做一个C包装,因为我需要在C项目中使用它。 我见过C++类包装器的例子,但我不想了解这个过程,我不能包装C++结构。
我要包装的结构:如何使用C++;C代码? 我试图为C++第三方库做一个C包装,因为我需要在C项目中使用它。 我见过C++类包装器的例子,但我不想了解这个过程,我不能包装C++结构。,c++,c,wrapper,C++,C,Wrapper,我要包装的结构: struct confGlobal{ long int device; string name; int number; string uid; string message; bool mode; confiGlobal():device{LONG_MAX}, number{INT_MAX}{} }; struct product{ string id; string name; }; struct
struct confGlobal{
long int device;
string name;
int number;
string uid;
string message;
bool mode;
confiGlobal():device{LONG_MAX}, number{INT_MAX}{}
};
struct product{
string id;
string name;
};
struct category{
unsigned char id;
string name;
string description;
category():id{UCHAR_MAX}{}
};
struct subCategory{
unsigned char id;
string name;
string description;
unsigned char idRoot;
subCategory():id{UCHAR_MAX}, idRoot{UCHAR_MAX}{}
};
struct confPartner{
vector<struct product> tableProduct;
vector<struct category> tableCategory;
vector<struct subCategory> tableSubCategory;
};
我需要填充这个结构并从C调用my_API::Instance()
,但是我的尝试没有成功
包装纸
#ifdef __cplusplus
extern "C" {
#endif
struct confGlobal_wpr; // An opaque type that we'll use as a handle
typedef struct confGlobal_wpr confGlobal_wpr;
confGlobal_wpr *confGlobal_create(unsigned int device,
char *name,
int number,
char *uid,
char *message,
unsigned char mode);
struct product_wpr{
char id[4];
char name[30];
};
typedef struct product_wpr product_wpr;
struct category_wpr{
unsigned char id;
char name[3];
char description[30];
};
typedef struct category_wpr category_wpr;
struct subcategory_wpr{
unsigned char id;
char name[3];
char description[30];
unsigned char idRoot;
};
typedef struct subCategory_wpr subCategory_wpr;
struct confPartner_wpr; // An opaque type that we'll use as a handle
typedef struct confPartner_wpr confPartner_wpr;
confPartner_wpr *confPartner_create(Product_wpr tableProducts[],
unsigned char numProducts,
Category_wpr tableCategories[],
unsigned char numCategories,
SubCategory_wpr tableSubCategories[],
unsigned char numSubCategories);
struct my_api_wpr;
typedef struct my_api_wpr my_api_wpr;
my_api_wpr *my_api_create(struct confGlobal_wpr cGlobal,
struct confPartner_wpr cPartner);
#ifdef __cplusplus
}
#endif
包装器
confGlobal_wpr *confGlobal_create(unsigned int device,
char *name,
int number,
char *uid,
char *message,
unsigned char mode)
{
confGlobal_wpr *cg;
struct confGlobal confiGlobal;
confiGlobal.name = name;
confiGlobal.device = device;
confiGlobal.number = number;
confiGlobal.uid = uid;
confiGlobal.message = message;
if (mode == 0)
confiGlobal.mode = false;
else
confiGlobal.mode = true;
return cg;
}
void confGlobal_destroy(confGlobal_wpr *cg)
{
if (cg == NULL)
return;
delete static_cast<confGlobal_wpr *>(cg->instance); // ERROR: invalid static_cast from type ‘confGlobal’ to type ‘confGlobal_wpr*’
free(cg);
}
confPartner_wpr *confPartner_create(product_wpr tableProducts_wpr[],
unsigned char numProducts,
category_wpr tableCategories_wpr[],
unsigned char numCategories,
subCategory_wpr tableSubCategories_wpr[],
unsigned char numSubCategories)
{
unsigned char i=0;
confPartner_wpr *cc;
struct confPartner cPartner;
vector< struct product> tableProduct;
vector< struct category> tableCategory;
vector< struct subCategory> tableSubCategory;
for (i=0; i<numProducts; i++)
{
struct product p;
p.id = tableProducts_wpr[i].id;
p.name = tableProducts_wpr[i].name;
tableProduct.push_back(p);
}
cPartner.tableProduct = tableProducts;
for (i=0; i<numCategories; i++)
{
struct category c;
c.id = tableCategories_wpr[i].id;
c.nombre = tableCategories_wpr[i].name;
c.descripcion = tableCategories_wpr[i].description;
tableCategory.push_back(c);
}
cPartner.tableCategory = tableCategory;
for (i=0; i<numSubCategories; i++)
{
struct subZona sc;
sc.id = tableSubCategories_wpr[i].id;
sc.name = tableSubCategories_wpr[i].name;
sc.description = tableSubCategories_wpr[i].description;
sc.idRoot = tableSubCategories_wpr[i].idRoot;
tableSubCategory.push_back(sc);
}
cPartner.tableSubCategory = tableSubCategory;
return cc;
}
my_api_wpr *my_api_create(struct confGlobal_wpr confiGlobal_wpr,
struct confPartner_wpr confiPartner_wpr)
{
my_api_wpr *my_api;
my_API *obj;
my_api = (typeof(my_api))malloc(sizeof(*my_api));
obj = my_API::Instance(confiGlobal_wpr, confiConsorcio_wpr);
/* With this compile and linked OK
confGlobal cg;
confPartner cc;
obj = my_API::Instance(cg, cc);
*/
my_api->obj = obj;
return my_api;
}
void my_api_destroy(ct_api_wpr *my_api)
{
if (my_api == NULL)
return;
delete static_cast<my_API *>(my_api->ptr_api); // ERROR: ‘virtual my_API::~my_API()’ is private within this context
free(my_api);
}
#include <algorithm>
#include "Foo.h"
#include "CWrappers.h"
// input and output to this C function should be understandable for C
BarWrapper createFoo(char *c)
{
// inside you can use C++
std::string data(c);
Bar bar(data);
Foo * foo = new Foo(bar);
BarWrapper barWrapper;
std::copy(data.begin(), data.end(), barWrapper.data);
return barWrapper; // pack data to C struct wrapper (that has no C++ specific)
}
包含C++和C++的原始数据类型以外的任何结构都不能以你想要的方式被包装。在这种特殊情况下,结构中有
::std::string
s。而且它们完全不能从C中合理地访问
<> P>结构中包含了<代码> BOOL ,我不知道C标准的更新版本是否有<代码> BoOL <代码>,或者定义为这样,它将导致在同一平台上用C++实现布局兼容结构。
这个问题有解决办法。但是它们涉及到在C中使用指向结构的不透明指针,并且总是调用函数来访问其方法。我将尝试创建一个示例,说明这对于一个非常简单的结构是如何工作的
更仔细地看一下您的代码,看起来您需要一种采用C结构和(在C++中)的thunk层手工将它转换为C++结构,并返回一个指向动态分配的C++结构的指针,然后将其传递给其他已经暴露于C.< /P> < P>的C++函数。您忘记了
首先,由于您使用“创建”样式的例程来构建结构并将它们作为指针返回,所以应该考虑使您的<代码> MyApAPI创建< /代码>函数接受指针。特别是因为生成的句柄类型是前向声明的结构,在C中没有可见的定义,并且您的C客户机不可能取消对它们的引用
这突出了另一个问题。您也没有正确使用C++中的句柄。 所以,一次只做一件事 您在C中的创建例程应声明为:my_api_wpr *my_api_create(struct confGlobal_wpr* cGlobal, struct confPartner_wpr* cPartner);
extern "C" struct confGlobal_wpr {
struct confGlobal instance;
};
extern "C" struct confPartner_wpr {
struct confPartner instance;
};
extern "C" struct my_api_wpr {
my_API *ptr;
};
现在,您的创作:
confGlobal_wpr *confGlobal_create(unsigned int device,
char *name,
int number,
char *uid,
char *message,
unsigned char mode)
{
confGlobal_wpr *cg = new confGlobal_wpr;
struct confGlobal& cGlobal = cg->instance; //<-- note the reference
// TODO: populate cGlobal as usual
return cg;
}
confPartner_wpr *confPartner_create(product_wpr tableProducts_wpr[],
unsigned char numProducts,
category_wpr tableCategories_wpr[],
unsigned char numCategories,
subCategory_wpr tableSubCategories_wpr[],
unsigned char numSubCategories)
{
confPartner_wpr *cc = new confPartner_wpr;
struct confPartner& cPartner = cc->instance; //<-- note the reference
// TODO: populate cPartner as usual
return cc;
}
my_api_wpr *my_api_create(struct confGlobal_wpr* cGlobal, struct confPartner_wpr* cPartner)
{
my_api_wpr *my_api = new my_api_wpr;
my_api->ptr = CT_API::Instance(cGlobal->instance, cPartner->instance);
return my_api;
}
confGlobal\u wpr*confGlobal\u create(无符号整数设备,
字符*名称,
整数,
字符*uid,
字符*消息,
无符号字符模式)
{
confGlobal\u wpr*cg=新的confGlobal\u wpr;
struct confGlobal&cGlobal=cg->instance;//instance;//ptr=CT\u API::instance(cGlobal->instance,cPartner->instance);
返回我的api;
}
你也应该添加相应的<代码>销毁< /COD>所有方法。
< P>在C项目中使用C++代码,你需要用C调用约定——外“C”(关闭C++名字的修饰/装饰)定义包装函数,并在C项目中调用它们。在C函数中,你可以使用C++代码。传递给C包装器函数的只有C理解的类型。您可以创建将数据传递给C包装函数的中间结构。然后,需要将数据复制到C++类期望的类型。在您的特定情况下,您错误地通过了PoPulalAxWPR包装器结构,但C++方法需要CODGONG,并且编译器对此直接抱怨。是可观察的代码片段,如何从C代码中使用C++代码: 福安
包装器confGlobal_wpr *confGlobal_create(unsigned int device,
char *name,
int number,
char *uid,
char *message,
unsigned char mode)
{
confGlobal_wpr *cg;
struct confGlobal confiGlobal;
confiGlobal.name = name;
confiGlobal.device = device;
confiGlobal.number = number;
confiGlobal.uid = uid;
confiGlobal.message = message;
if (mode == 0)
confiGlobal.mode = false;
else
confiGlobal.mode = true;
return cg;
}
void confGlobal_destroy(confGlobal_wpr *cg)
{
if (cg == NULL)
return;
delete static_cast<confGlobal_wpr *>(cg->instance); // ERROR: invalid static_cast from type ‘confGlobal’ to type ‘confGlobal_wpr*’
free(cg);
}
confPartner_wpr *confPartner_create(product_wpr tableProducts_wpr[],
unsigned char numProducts,
category_wpr tableCategories_wpr[],
unsigned char numCategories,
subCategory_wpr tableSubCategories_wpr[],
unsigned char numSubCategories)
{
unsigned char i=0;
confPartner_wpr *cc;
struct confPartner cPartner;
vector< struct product> tableProduct;
vector< struct category> tableCategory;
vector< struct subCategory> tableSubCategory;
for (i=0; i<numProducts; i++)
{
struct product p;
p.id = tableProducts_wpr[i].id;
p.name = tableProducts_wpr[i].name;
tableProduct.push_back(p);
}
cPartner.tableProduct = tableProducts;
for (i=0; i<numCategories; i++)
{
struct category c;
c.id = tableCategories_wpr[i].id;
c.nombre = tableCategories_wpr[i].name;
c.descripcion = tableCategories_wpr[i].description;
tableCategory.push_back(c);
}
cPartner.tableCategory = tableCategory;
for (i=0; i<numSubCategories; i++)
{
struct subZona sc;
sc.id = tableSubCategories_wpr[i].id;
sc.name = tableSubCategories_wpr[i].name;
sc.description = tableSubCategories_wpr[i].description;
sc.idRoot = tableSubCategories_wpr[i].idRoot;
tableSubCategory.push_back(sc);
}
cPartner.tableSubCategory = tableSubCategory;
return cc;
}
my_api_wpr *my_api_create(struct confGlobal_wpr confiGlobal_wpr,
struct confPartner_wpr confiPartner_wpr)
{
my_api_wpr *my_api;
my_API *obj;
my_api = (typeof(my_api))malloc(sizeof(*my_api));
obj = my_API::Instance(confiGlobal_wpr, confiConsorcio_wpr);
/* With this compile and linked OK
confGlobal cg;
confPartner cc;
obj = my_API::Instance(cg, cc);
*/
my_api->obj = obj;
return my_api;
}
void my_api_destroy(ct_api_wpr *my_api)
{
if (my_api == NULL)
return;
delete static_cast<my_API *>(my_api->ptr_api); // ERROR: ‘virtual my_API::~my_API()’ is private within this context
free(my_api);
}
#include <algorithm>
#include "Foo.h"
#include "CWrappers.h"
// input and output to this C function should be understandable for C
BarWrapper createFoo(char *c)
{
// inside you can use C++
std::string data(c);
Bar bar(data);
Foo * foo = new Foo(bar);
BarWrapper barWrapper;
std::copy(data.begin(), data.end(), barWrapper.data);
return barWrapper; // pack data to C struct wrapper (that has no C++ specific)
}
使用
char*
,而不是使用看似任意长度的char
,因为在许多情况下,30个字符肯定太小了。您可能会发现,将c:[c][/]>代码>或<代码> char */COD>到C++ >代码> STD::String 不可能没有C++。为什么要通过PoGualLuxWPR-方法需要使用FuCuGLULL来使用C++代码?您需要用C调用约定定义包装函数,(ExtC),并在C项目中调用它们。在那些导出函数中,你可以使用C++代码。我已经对我的代码进行了修改,目前效果很好。现在,我了解了一些包装事实,我需要包装许多其他结构和方法。还有一个问题:我如何销毁指针包装结构(confGlobal)和指针包装类(ct_api_wpr)?我在我最初的ask中添加了销毁方法。我不知道你可以在结构上使用extern“C”
。你一定要吗?它有什么用吗?我怀疑不是这样。@crossmax嗯,对于API本身来说很奇怪,因为它实际上是一个单例。因此,从技术上讲,myapi\ucreate
可以是myapi\uinitialize
而不返回指针。对于confGlobal\u wpr
您的销毁函数将只是void confGlobal\u destroy(confGlobal\u wpr*confGlobal){delete confGlobal;}
和类似的confPartner\u wpr
@Omnifarious,实际上我不是100%确定,因为结构已经在头中被转发声明为extern“C”
。我所做的基本上与在extern“C”
中包装定义相同。但这可能不是必需的,因此这可能是错误的。当然,在extern
的传统用法中,据我所知,它只在声明中需要。我不需要在C中写C++库包装器大约20年;如果你找到了答案,请在这里写个便条。
#include <string>
class Bar
{
public:
Bar(std::string s) : s_(s)
{
}
std::string s_;
};
class Foo
{
public:
Foo(Bar) {}
};
struct BarWrapper
{
char data[100] = "";
};
#ifdef __cplusplus
extern "C" {
#endif
BarWrapper createFoo(char *c);
#ifdef __cplusplus
}
#endif
#include <algorithm>
#include "Foo.h"
#include "CWrappers.h"
// input and output to this C function should be understandable for C
BarWrapper createFoo(char *c)
{
// inside you can use C++
std::string data(c);
Bar bar(data);
Foo * foo = new Foo(bar);
BarWrapper barWrapper;
std::copy(data.begin(), data.end(), barWrapper.data);
return barWrapper; // pack data to C struct wrapper (that has no C++ specific)
}
#include "CWrappers.h"
int main()
{
BarWrapper barWrapper = createFoo((char *)"test");
}