如何从C文件调用C ++类及其方法 [英] How to call a c++ class and its method from a c file
问题描述
我试图访问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 classM
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 $ c $中的
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屋!