如何从ac文件中调用c ++类及其方法

16 c c++

我试图访问一个C++类并从.c文件中调用它的方法.

我谷歌这个话题,找到这个http://developers.sun.com/solaris/articles/mixing.html

它说:

您可以用extern "C"C++ 编写访问类M对象的函数,并从C代码中调用它们.

这是一个用于调用成员函数的C++函数foo:

extern "C" int call_M_foo(M* m, int i) { return m->foo(i); }
Run Code Online (Sandbox Code Playgroud)

我的问题是我在哪里放线?在我的C++ .h文件中?还是C .h档?

它继续说:

以下是使用类的C代码示例M:

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);
}
Run Code Online (Sandbox Code Playgroud)

但是我如何/在哪里创建M我的C文件中的类?我在哪里放上面的代码?C .h档?C++ .h文件?还是C .c档?

谢谢.

感谢GMan的详细解答.我确实按照你的建议.但是我的.c文件中出现编译错误.

main.c:33:
./ some_class.h :24:错误:在' '令牌之前预期'=',',',';','asm'或' 属性 ' ./some_class.h:25:错误:预期')'在' '令牌 ./some_class.h:26:错误:预期')'在'*'令牌之前

这是我的some_class.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
Run Code Online (Sandbox Code Playgroud)

出于某种原因,我的C编译器不喜欢extern "C"GMAN的原始some_test.h.所以我必须修改到上面.看起来C编译器不喜欢/理解这一struct M;行.

任何想法将不胜感激.

GMa*_*ckG 31

您的头文件,在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);
Run Code Online (Sandbox Code Playgroud)

然后你的源文件:

#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);
}
Run Code Online (Sandbox Code Playgroud)

现在编译该源,并链接到它.您的C源将是这样的:

#include "some_class.h"

some_class* myInstance = some_class_new();

int i = some_class_some_method(myInstance, 10.0f);

some_class_delete(myInstance);
Run Code Online (Sandbox Code Playgroud)

如果你真的想要混合C和C++,你会想要宏.


以下是一些示例宏,可以使这更容易:

// 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); }
Run Code Online (Sandbox Code Playgroud)

等等.我们的标题/来源变为:

// 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);
Run Code Online (Sandbox Code Playgroud)

这更加简洁.它可以变得更简单(可能)与可变宏,但这是非标准的,我把它留给你.:]此外,您可以为正常的非成员函数创建宏.


需要注意的是C不用知道引用是什么.如果要绑定到引用,最好的办法可能就是手动编写导出定义.(但我会考虑一下,也许我们可以自动获得它).

想象一下,我们some_class采用了floatby(非const)引用(无论出于何种原因).我们像这样定义函数:

// header
// pass by pointer!                                     v
EXPORT_C_CLASS_METHOD_1(some_class, some_method, int, float*) ;

// source
EXPORT_C_CLASS_METHOD_1(some_class, some_method, int, float*) 
{
    // dereference pointer; now can be used as reference
    return this->some_method(*p1);
}
Run Code Online (Sandbox Code Playgroud)

我们走了.C将使用指针与引用接口:

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

我们通过f"参考" 传递.