C++ 如何调用c++;类及其方法,从c文件

C++ 如何调用c++;类及其方法,从c文件,c++,c,C++,C,我试图访问C++类,并从 .c/c>文件中调用它的方法。< /p> 我用谷歌搜索这个主题,找到了这个 它说: C++中可以写“代码>外部”C“函数”,访问类 M< /Cord>对象,并从C代码调用它们。 这里是一个C++函数,用来调用成员函数 Foo:< /强> extern "C" int call_M_foo(M* m, int i) { return m->foo(i); } struct M; // you can supply

我试图访问C++类,并从<代码> .c/c>文件中调用它的方法。< /p> 我用谷歌搜索这个主题,找到了这个

它说:

C++中可以写“代码>外部”C“<代码>函数”,访问类<代码> M< /Cord>对象,并从C代码调用它们。

<强>这里是一个C++函数,用来调用成员函数<代码> Foo:< /强>

extern "C" int call_M_foo(M* m, int i) { return m->foo(i); }
struct M;                       // you can supply only an incomplete declaration

int call_M_foo(struct M*, int); // declare the wrapper function

int f(struct M* p, int j)       // now you can call M::foo
{
  return call_M_foo(p, j);
}
我的问题是,我应该把绕线放在哪里?在我的C++ <代码> .h >代码>文件中?还是C
.h
文件

它接着说:

下面是一个使用类
M
的C代码示例:

extern "C" int call_M_foo(M* m, int i) { return m->foo(i); }
struct M;                       // you can supply only an incomplete declaration

int call_M_foo(struct M*, int); // declare the wrapper function

int f(struct M* p, int j)       // now you can call M::foo
{
  return call_M_foo(p, j);
}
但是如何/在哪里在我的C文件中创建类
M
? 我应该把上面的代码放在哪里?C
.h
文件?C++ <代码> .h /代码>文件?还是C
.C
文件

多谢各位

感谢GMan的详细回答。 我确实听从了你的建议。但是我的
.c
文件中出现编译错误

main.c:33:
./some_class.h:24:错误:应为“=”,“,”,“;”,”“”标记之前的asm'或'属性 /some_class.h:25:error:expected')在“”标记之前
./some_class.h:26:error:expected')在“*”标记之前

这是我的
一些课程.h
24-26

#ifdef __cplusplus 
class M {

public:
  M();
  virtual ~M(); 

  void method1(char* name, char* msg);
};

extern "C" {
#else
struct M;
#endif

  /* access functions line 24-26 are here*/ 
  M* M_new(void);
  void M_delete(M*);
  void M_method1(M*, char*, char*);
#ifdef __cplusplus 
}
#endif
出于某种原因,我的C编译器不喜欢
GMan中的
外部“C”
的原始
测试.h
。所以我必须修改到上面。C编译器似乎不喜欢/不理解结构M


任何想法都将被赏识。

你需要在C++头文件和实现文件中分割它。

foo.h:

extern "C" int call_M_foo(M* m, int i);
struct M;
extern "C" M* create_M();
foo.cc:

extern "C" int call_M_foo(M* m, int i) {
    return m->foo(i);
}
extern "C" M* create_M() {
    return new M;
}
要创建M类型的对象,您需要一个类似的函数:

foo.h:

extern "C" int call_M_foo(M* m, int i);
struct M;
extern "C" M* create_M();
foo.cc:

extern "C" int call_M_foo(M* m, int i) {
    return m->foo(i);
}
extern "C" M* create_M() {
    return new M;
}

您链接到的站点已经有了答案:

您可以在 由C和C共享的头文件 C++代码:

您最多可以声明一个函数 重载集的外部“C” 下面是 包装函数:


基本上,可以在两个共享的头上声明函数原型,如果C.是C++,则在函数中可以添加外部“C”修饰符,以确保函数可以从一个对象中访问,然后在C++代码中像往常一样在函数中定义函数的主体,如在类中需要的话,在C中使用函数,像正常值一样。

您的头文件,它在C和C++代码之间共享:

#ifdef __cplusplus // only actually define the class if this is C++

class some_class
{
    public:
        int some_method(float);
};

#else

// C doesn't know about classes, just say it's a struct
typedef struct some_class some_class; 

#endif

// access functions
#ifdef __cplusplus
    #define EXPORT_C extern "C"
#else
    #define EXPORT_C
#endif

EXPORT_C some_class* some_class_new(void);
EXPORT_C void some_class_delete(some_class*);
EXPORT_C int some_class_some_method(some_class*, float);
然后您的源文件:

#include "some_foo.h"

int some_class::some_method(float f)
{
    return static_cast<int>(f);
}

// access functions
EXPORT_C some_class* some_class_new(void)
{
    return new some_class();
}

EXPORT_C void some_class_delete(some_class* this)
{
    delete this;
}

EXPORT_C int some_class_some_method(some_class* this, float f)
{
    return this->some_method(f);
}

<>如果你认真地想混合C和C++,你会想要宏的< /P>
以下是一些示例宏,它们可以使这一过程变得更简单:

// in something like c_export.h
// extern "C" macro
#ifdef __cplusplus
    #define EXPORT_C extern "C"
#else
    #define EXPORT_C
#endif

// new
#define EXPORT_C_CLASS_NEW(classname) EXPORT_C \
            classname * classname##_new(void)

#define EXPORT_C_CLASS_NEW_DEFINE(classname) \
            EXPORT_C_CLASS_NEW(classname) \
            { return new classname (); }

// repeat as much as you want. allows passing parameters to the constructor
#define EXPORT_C_CLASS_NEW_1(classname, param1) EXPORT_C \
            classname * classname##_new( param1 p1)

#define EXPORT_C_CLASS_NEW_1_DEFINE(classname, param1) \
            EXPORT_C_CLASS_NEW_1(classname, param1) \
            { return new classname (p1); }

// delete
#define EXPORT_C_CLASS_DELETE(classname) EXPORT_C \
            void classname##_delete( classname * this)

#define EXPORT_C_CLASS_DELETE_DEFINE(classname) \
            EXPORT_C_CLASS_DELETE(classname) \
            { delete this; }

// functions
#define EXPORT_C_CLASS_METHOD(classname, methodname, ret) EXPORT_C \
            ret classname##_##methodname##( classname * this)

#define EXPORT_C_CLASS_METHOD_DEFINE(classname, methodname, ret) \
            EXPORT_C_CLASS_METHOD(classname, methodname, ret) \
            { return this->##methodname##(); }

// and repeat as necessary.
#define EXPORT_C_CLASS_METHOD_1(classname, methodname, ret, param1) EXPORT_C \
            ret classname##_##methodname( classname * this, param1 p1)

#define EXPORT_C_CLASS_METHOD_1_DEFINE(classname, methodname, ret, param1) \
            EXPORT_C_CLASS_METHOD_1(classname, methodname, ret, param1) \
            { return this->##methodname##(p1); }
等等。我们的标题/来源变成:

// header
#include "c_export.h" // utility macros

#ifdef __cplusplus // only actually define the class if this is C++

class some_class
{
    public:
        int some_method(float);
};

#else

// C doesn't know about classes, just say it's a struct
typedef struct some_class some_class; 

#endif

// access functions
EXPORT_C_CLASS_NEW(some_class);
EXPORT_C_CLASS_DELETE(some_class);
EXPORT_C_CLASS_METHOD_1(some_class, some_method, int, float);

// source
#include "some_foo.h"

int some_class::some_method(float f)
{
    return static_cast<int>(f);
}

// access functions
EXPORT_C_CLASS_NEW_DEFINE(some_class);
EXPORT_C_CLASS_DELETE_DEFINE(some_class);
EXPORT_C_CLASS_METHOD_1_DEFINE(some_class, some_method, int, float);
我们走了。C将使用指针与引用接口:

// c source, if some_method took a reference:
float f = 10.0f;
int i = some_class_some_method(myInstance, &f);

我们通过“参考”传递
f

您这里有几个问题,所以我将分别回答

我的问题是,我应该把绕线放在哪里?在我的C++ .h文件中?还是c.h文件

<> >代码>外部“C”<代码>行进入C++文件。它本质上告诉编译器 限制所有的代码,将代码“>外部”C”/代码>块到C++的C子集,并 相应地导出在此区域中声明的函数

但是如何/在哪里在我的c文件中创建类M

你不能。C没有类的概念,也绝对没有 直接实例化类的方法。你必须导出一个C函数 在C++文件中创建类并将其作为指针返回。那你呢 可以在C应用程序周围传递该指针。实际上,您不能修改 直接在C应用程序中初始化,因为C不支持类,并且 您的C++编译器可以插入“隐藏”变量来进行内部簿记。 类的实际声明

我应该把上面的代码放在哪里

使用
struct
ure指针的代码段位于C文件中。你是 被迫使用
struct
ure指针,因为C根本不支持类。 您可以在C实现中的任何位置使用该函数进行函数调用
文件,就像普通的C函数调用一样。

您需要的所有信息都在您提供的链接中。您只需要理解C和C++代码之间需要严格的分离。
  • C++代码可以调用任何C代码
  • C代码通常不能调用任何C++代码。 C函数可以用C++代码实现。 <> P. >理解的关键部分是C和C++编译器在以不同的方式制作对象文件时,函数名会被忽略,所以它们通常不能在链接时进行交互操作,除了C++可以通过使用<代码>外部> C”//> > /P >来提示不同之处。 原型:
    void f(int)可能会被C编译器损坏: > F f>代码>,但是C++编译器可能会选择一个非常不同的名称,例如“代码> fytnt/CODE >,因此链接器不知道它们应该是相同的。”
    然而:

    extern“C”void f(int)

    将被C++编译器修改为Fi,但C编译器会在 Extn“C”< /C>中窒息。为了避免这种情况,您应该使用以下方法:

    #ifdef __cplusplus
    extern "C" {
    #endif
    
    void f(int);
    
    #ifdef __cplusplus
    } /* closing brace for extern "C" */
    #endif
    
    现在,上面的整个部分都可以保存在一个.h文件中,正如
    sun.com
    文章所述,它是一个混合语言标题

    这意味着.c或.cpp文件可以
    #包含
    此头文件,并且代码可以调用
    f()
    a.c或.cpp文件都可以
    #包括
    此头并实现它:

    void f()
    {
    }
    

    现在的好一点是.cpp文件可以实现它调用任何它喜欢的C++代码。 现在回答您的具体问题:

  • 第一个代码示例只能放在.cpp文件中
  • 第二个代码示例只能放在.c文件中
  • 额外的