Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用C++;C代码? 我试图为C++第三方库做一个C包装,因为我需要在C项目中使用它。 我见过C++类包装器的例子,但我不想了解这个过程,我不能包装C++结构。_C++_C_Wrapper - Fatal编程技术网

如何使用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++函数。您忘记了 CTA:API:实例< /C> >不理解C中已经创建的“句柄”类型来包装C++结构。这正是错误消息告诉您的,如果您阅读它的话。你必须把这些转换成合适的C++类型。

首先,由于您使用“创建”样式的例程来构建结构并将它们作为指针返回,所以应该考虑使您的<代码> MyApAPI创建< /代码>函数接受指针。特别是因为生成的句柄类型是前向声明的结构,在C中没有可见的定义,并且您的C客户机不可能取消对它们的引用

这突出了另一个问题。您也没有正确使用C++中的句柄。 所以,一次只做一件事

您在C中的创建例程应声明为:

my_api_wpr *my_api_create(struct confGlobal_wpr* cGlobal, struct confPartner_wpr* cPartner);
在C++方面,需要实际定义句柄类型。比如:

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");
        }