如何从C文件调用C ++类及其方法 [英] How to call a c++ class and its method from a c file

查看:84
本文介绍了如何从C文件调用C ++类及其方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图访问C ++类并从 .c 文件调用其方法。

I am trying to access a C++ class and call its method from a .c file.

I google这个主题,找到这个 http://developers.sun.com/solaris/articles/ blend.html

I google this topic and find this http://developers.sun.com/solaris/articles/mixing.html

它说:


您可以编写C ++中的外部 C 函数可访问类 M 对象并从C代码中调用它们。

You can write extern "C" functions in C++ that access class M objects and call them from C code.

这是一个C ++函数,旨在调用成员函数 foo

Here is a C++ function designed to call the member function foo:

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

我的问题是我应该在大约行中放置什么?在我的C ++ .h 文件中?还是C .h 文件?

My question is where do I put the about line? In my C++ .h file? Or C .h file?

然后继续说:

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

Here is an example of C code that uses class 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);
}

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

But how/where do I create the class M in my C file? And where do I put the above code? C .h file? C++ .h file? Or C .c file?

谢谢。

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

Thank you for GMan's detailed answer. I did follow your suggestion. But I get compile error in my .c file.


main.c: 33:

./some_class.h:24:错误:在'属性' >'令牌

./some_class.h:25:错误:预期')'在''令牌

./some_class.h:26:错误:预期'*'令牌之前的')'

main.c:33:
./some_class.h:24: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘attribute’ before ‘’ token
./some_class.h:25: error: expected ‘)’ before ‘
’ token
./some_class.h:26: error: expected ‘)’ before ‘*’ token

这是我的 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

出于某种原因,我的C编译器不喜欢 GMan 的原始 some_test.h extern C c>。所以我必须修改到上面。似乎C编译器不喜欢/不理解 struct M; 行。

For some reason, my C compiler does not like extern "C" in GMan's original some_test.h. So I have to modify to above. It seems like the C compiler does not like/understand the struct M; line.

任何想法都会很多

推荐答案

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

Your header file, which is shared between your C and C++ code:

#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源代码将是这样的:

Now compile that source, and link to it. Your C source would be something like:

#include "some_class.h"

some_class* myInstance = some_class_new();

int i = some_class_some_method(myInstance, 10.0f);

some_class_delete(myInstance);

如果您认真考虑将C和C ++混合使用,则需要使用宏。

If you're serious about mixing C and C++, you'll want macro's.

以下是一些示例宏,它们可以使操作简单得多:

Here are some sample macro's that would make this much easier:

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

依此类推。我们的标头/源变为:

And so on. Our header/source becomes:

// 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);

这更加简洁。使用可变参数宏可以使它更简单(可能),但这不是标准的,我留给您。 :]另外,您可以为普通的非成员函数创建宏。

And that's much more concise. It could be made simpler (possibly) with variadic macro's, but that's non-standard and I leave that to you. :] Also, you can make macro's for normal non-member functions.

请注意,C不会 知道什么是引用。如果要绑定到引用,最好的选择就是手动编写导出定义。 (但是我会考虑的,也许我们可以自动获取它。)

Note that C does not know what references are. If you want to bind to a reference, your best bet is probably just to write the export definition manually. (But I'll think about it, maybe we can get it automatically).

想象一下我们的 some_class 接受了 float 通过(非常量)引用(无论出于何种原因)。我们将这样定义函数:

Imagine our some_class took the float by (non-const)reference (for whatever reason). We'd define the function like so:

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

然后我们走了。 C将改为使用带有指针的引用进行接口:

And there we go. C would interface with references with pointers instead:

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

然后我们通过引用传递 f

And we pass f "by reference".

这篇关于如何从C文件调用C ++类及其方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆