【问题标题】:How to use c++ objects in c?如何在 c 中使用 c++ 对象?
【发布时间】:2012-08-15 14:21:54
【问题描述】:

我的视觉工作室中有 2 个项目解码器和解码器。一个有 C 代码,另一个有 C++ 代码,分别使用 stl。如何在解码项目中的 c 代码中实例化 c++ 类?

for e.g.
//instantiating object
reprVectorsTree *r1 = new reprVectorsTree(reprVectors1,8);
//using one of its function
r1->decode(code);

为此我需要做什么?

如何访问其他项目的文件?

如何利用 C 文件中现有的 c++ 代码?

--------编辑---------- 我有这样的课

class Node//possible point in our input space
{
public:
    std::vector<float> valuesInDim;//values in dimensions
    std::vector<bool> code;
    Node(std::vector<float>value);
    Node::Node(float x, float y);
Node::Node(std::vector<float> value,std::vector<bool> binary);


};

如何在 c++ 中使用上述类? 如果 C 只允许结构,我如何将其映射到结构?

【问题讨论】:

  • 您的 C 代码是否使用 C++ 编译器进行编译?如果您可以用 C++ 编译所有内容,那将是最简单的解决方案。
  • 那么,您是在问如何在不同的编程语言中使用来自编程语言的代码?
  • 您可以使用 extern "C" 在 C++ 中创建一种包装 DLL,用于调用类并将类实例包装在结构中的所有内容(我不知道 DLL 是否可以做到这一点,我一个对 DLL 一无所知的 Linux 人)。
  • @Lanaru:是的,但这比询问如何在 PHP 中使用 Lisp 对象或类似的东西更可行。 C 和 C++ 非常相似,大多数 C 和 C++ 编译器都让它们(大部分)共享一个 ABI。让 C 和 C++ 交互比大多数其他组合要容易得多。
  • calling c++ code from c 的可能重复项

标签: c++ c


【解决方案1】:

给 C++ 模块一个 C 接口:

ma​​gic.hpp:

struct Magic
{
    Magic(char const *, int);
    double work(int, int);
};

ma​​gic.cpp:(实现Magic。)

ma​​gic_interface.h:

struct Magic;

#ifdef __cplusplus
extern "C" {
#endif

typedef Magic * MHandle;
MHandle create_magic(char const *, int);
void    free_magic(MHandle);
double  work_magic(MHandle, int, int);

#ifdef __cplusplus
}
#endif

ma​​gic_interface.cpp:

#include "magic_interface.h"
#include "magic.hpp"

extern "C"
{
    MHandle create_magic(char const * s, int n) { return new Magic(s, n); }
    void    free_magic(MHandle p) { delete p; }
    double  work_magic(MHandle p, int a, int b) { return p->work(a, b); }
}

现在 C 程序可以#include "magic_interface.h" 并使用代码:

MHandle h = create_magic("Hello", 5);
double d = work_magic(h, 17, 29);
free_magic(h);

(您甚至可能想将MHandle 定义为void * 并在各处添加强制转换,以避免在C 标头中声明struct Magic。)

【讨论】:

  • 调用 magic.cpp magic_interface.cpp 会更有意义,并在 magic.cpp 中实现魔法的 c++ 实现
  • magic.cpp 中的函数需要用 extern "C" 括起来,否则会出现链接错误。在 MSVC2010 上测试。
  • @user494461:C++ 没有区别。 structclass 都指定类类型(我认为从我对构造函数和成员函数的使用中可以明显看出)。
  • @user494461 你是用 C 编译代码吗?请注意包装器“magic_interface.cpp”的文件类型。它应该是 .cpp,而不是 .c
  • @2i3r:嗯,不是以您可以暴露给 C 的方式,但最终这并不重要:您可以改为将 MHandle 设为 void* 的别名,然后进行转换在你的 C++ 代码中来回切换,到你喜欢的任何 C++ 对象类型。
【解决方案2】:

使用 C++ 导出函数创建用于实例化 C++ 对象的包装器。然后从 C 代码中调用这些函数以生成对象。

由于一个是面向函数的,另一个是面向对象的,你可以在你的包装器中使用一些想法:-

  1. 为了复制类成员,将一个等效的预指定结构从 C 代码传递到相应的 C++ 函数以获取数据。
  2. 尝试使用函数指针,因为它会降低成本,但要小心它们也可能被利用。

A few other ways.

【讨论】:

    【解决方案3】:

    你需要用 C 编写一个包装器。

    类似这样的:

    在class.h中:

    struct A{
       void f();
    }
    

    在class.cpp中:

    void A::f(){
    }
    

    包装器.cpp:

    #include "wrapper.h"
    void fWrapper(struct A *a){a->f();};
    struct A *createA(){
       A *tmp=new A();
       return tmp;
    }
    
    void deleteA(struct A *a){
     delete a;
    }
    

    C 的 wrapper.h:

    struct A;
    void fWrapper(struct A *a);
    A *createA();
    

    C 程序:

    #include "wrapper.h"
    int main(){
        A *a;
        a=createA();
        fWrapper(a);
        deleteA(a);
    }
    

    【讨论】:

    • 我有类,而不是结构,我可以在这里简单地替换它吗?
    • 我认为 C 没有 class 关键字。 (c++ 中的结构体与结构体类似,但具有不同的默认访问说明符)
    • 不知道。当我使用包装器时,我从不需要使用类。您可能可以在 c++ 文件中命名它们的类和包装文件中的结构。但这可能会导致未定义的行为
    【解决方案4】:

    简单来说,您只需执行以下操作:

    1. 编写一个接口函数,将所有类函数(构造函数、析构函数、成员函数)转换为纯函数,封装成extern "C"{ }
    2. 将指向类的指针转换为指向 void 的指针,并且小心在您定义“纯函数”的任何地方使用类型转换
    3. 在 C 代码中调用纯函数。

    例如,这是我的简单 Rectangle 类:

    /*** Rectangle.h ***/
    class Rectangle{
    private:
        double length;
        double breadth;
    public:
        Rectangle(double iLength, double iBreadth);
        ~Rectangle();
        double getLength();
        double getBreadth();
    };
    
    /*** Rectangle.cpp ***/
    #include "Rectangle.h"
    #include <iostream>
    extern "C" {
        Rectangle::Rectangle(double l, double b) {
            this->length = l;
            this->breadth = b;
        }
    
        Rectangle::~Rectangle() {
            std::cout << "Deleting object of this class Rectangle" << std::endl;
        }
    
        double Rectangle::getLength() {
            return this->length;
        }
    
        double Rectangle::getBreadth() {
            return this->breadth;
        }
    }
    

    现在这是我将类函数转换为纯函数的接口。注意指向类的指针是如何处理的!

    /*** RectangleInterface.h ***/
    #ifdef __cplusplus
    extern "C" {
    #endif
        typedef void * RHandle;
        RHandle create_Rectangle(double l, double b);
        void    free_Rectangle(RHandle);
        double  getLength(RHandle);
        double  getBreadth(RHandle);
    
    #ifdef __cplusplus
    }
    #endif
    
    /*** RectangleInterface.cpp ***/ 
    #include "RectangleInterface.h"
    #include "Rectangle.h"
    extern "C"
    {
        RHandle create_Rectangle(double l, double b){
            return (Rectangle*) new Rectangle(l, b);
        };
        void free_Rectangle(RHandle p){
            delete (Rectangle*) p;
        }
        double getLength(RHandle p){
            return  ((Rectangle*) p)->getLength();
        }
        double getBreadth(RHandle p){
            return ((Rectangle*)p)->getBreadth();
        }
    }
    

    现在我可以在我的“.c”文件中使用这些接口函数,如下所示。我只需在此处包含 RectangleInterface.h 函数,其余的由其函数处理。

    /*** Main function call ***/
    #include <stdio.h>
    #include "RectangleInterface.h"
    
    int main()
    {
        printf("Hello World!!\n");
        RHandle myRec = create_Rectangle(4, 3);
        printf("The length of the rectangle is %f\n", getLength(myRec));
        printf("The area of the rectangle is %f\n", (getLength(myRec)*getBreadth(myRec)));
        free_Rectangle(myRec);
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2016-11-23
      • 2016-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多