这个问题已经在这里有一个答案:
- 从“C”代码中调用“C ++”类的成员函数 1个回答
我有一个C ++类,我有一些C编译的文件它。
我想打电话给它在C ++中定义的函数,实际上C ++类,所以我要去怎么办?
以下声明,以显示我说什么:有可能会有语法错误:
serial_comm.cpp
class MyClass {
void sendCommandToSerialDevice(int Command, int Parameters, int DeviceId) {
//some codes that write to serial port.
}
}
external.c
int main(int argc, char ** argv) {
//what am I going to write here?
}
Answer 1:
解决这个问题的常见的方法是提供一个C包装API。 编写一个C函数,接受一个指向MyClass
对象(如MyClass
无效C,你将需要提供一些绰号,最简单的一个是移动void*
左右)和参数的其余部分。 然后里面C ++执行函数调用:
extern "C" void* MyClass_create() {
return new MyClass;
}
extern "C" void MyClass_release(void* myclass) {
delete static_cast<MyClass*>(myclass);
}
extern "C" void MyClass_sendCommandToSerialDevice(void* myclass, int cmd, int params, int id) {
static_cast<MyClass*>(myclass)->sendCommandToSerialDevice(cmd,params,id);
}
那么C代码使用C API来创建对象,调用函数与释放对象:
// C
void* myclass = MyClass_create();
MyClass_sendCommandToSerialDevice(myclass,1,2,3);
MyClass_release(myclass);
Answer 2:
你必须通过一个额外的参数,与对象的地址来调用该函数。 就像是:
extern "C" void SendCommandToSerialDevice( void* object,
int command, int parameters, int deviceId )
{
static_cast<MyClass*>( object)->sendCommandToSerialDevice(
command, parameters, deviceId );
}
main
的意志,当然,必须以某种方式找到的类的实例。
编辑:
至于在其他的答案带来了一些要点:
在你的榜样,您编译main
为C.这是不确定的行为,并在实践中可能意味着你的构造不会在静态对象调用。 (如果你的代码是一个DLL,你确定。该标准不说的DLL的事情,但在实践中,他们的工作。)
如果你用异常的方式报告错误,那么你就必须改变你的签名在一些其他的方式来报告他们,包装你的代码来捕获所有异常,并将它们转换为C约定。 (因为你的函数没有返回值,这是很容易的返回码的手段来处理。)
Answer 3:
如果你想这样做正确
serial_comm_wrapper.h
#ifdef __cpluscplus
class MyClass;
extern "C" {
#else
struct MyClass;
typedef struct MyClass MyClass;
#endif
MyClass *MyClass_new();
void MyClass_sendCommandToSerialDevice(MyClass *instance, int Command, int Parameters, int DeviceId);
#ifdef __cpluscplus
}
#endif
serial_comm_wrapper.cc
#include "serial_comm_wrapper.h"
#include "serial_comm.hh"
MyClass *MyClass_new()
{
return new MyClass();
}
void MyClass_sendCommandToSerialDevice(MyClass *instance, int Command, int Parameters, int DeviceId)
{
instance->sendCommandToSerialDevice(command, Parameters, DeviceID);
}
external.c
#include "serial_comm_wrapper.h"
int main(int argc, char ** argv) {
MyClass *instance = MyClass_new();
MyClass_sendCommandToSerialDevice(instance, ...);
}
Answer 4:
你不能只是去调用从C C ++代码
您将需要产生一个C ++接口,可以从C调用
像这样的事情
// interface.h
#ifdef __cplusplus
extern "C" {
#endif
void createMyclass();
void callMyclassSendCommandToSerialDevice(int Command, int Parameters, int DeviceId);
void destroyMyclass();
#ifdef __cplusplus
extern }
#endif
然后,你这样做:
static MyClass *myclass;
void createMyclass()
{
try
{
myclass = new MyClass;
}
catch(...)
{
fprintf(stderr, "Uhoh, caught an exception, exiting...\n");
exit(1);
}
}
void callMyclassSendCommandToSerialDevice(int Command, int Parameters, int DeviceId)
{
// May need try/catch here.
myclass->sendCommandToSerialDevice(Command, Parameters, DeviceId);
}
void destroyMyclass()
{
delete myclass;
}
请注意,它的当务之急是你不要让“例外”穿墙的C代码,因为这是明确的未定义的行为。
Answer 5:
您不能直接在C调用C ++方法相反,你可以创建一个C包装,然后调用:
C / C ++兼容头文件:
#ifdef __cplusplus
extern "C" {
#endif
struct MyClass;
MyClass *new_MyClass();
void MyClass_sendCommandToSerialDevice(MyClass *c, int Command, int Parameters, int DeviceID);
#ifdef __cplusplus
} // extern "C"
#endif
实现(.cpp文件)
#include "my_c_compatiblity_header.h"
#include "MyClass.h"
extern "C" MyClass *new_MyClass() { return new MyClass(); }
extern "C"
void MyClass_sendCommandToSerialDevice(MyClass *c, int Command, int Parameters, int DeviceID) {
c->sendCommandToSerialDevice(Command, Parameters, DeviceID);
}
main.c中
int main(int argc, char ** argv) {
MyClass *c = new_MyClass();
MyClass_sendCommandToSerialDevice(c, 1, 0, 123);
}
当然,由于资源和错误处理可以是C和C ++不同的代码,你就必须制定出如何处理你的情况相结合。 例如上面只是一个泄漏MyClass
对象,而不是清理,并没有做有关异常的事情。
文章来源: How to call a C++ method from C? [duplicate]