tập tin của bạn tiêu đề, được chia sẻ giữa C và 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);
Sau đó bạn nguồn file:
#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);
}
Bây giờ biên dịch mã nguồn đó, và liên kết với nó. Nguồn C của bạn sẽ giống như sau:
#include "some_class.h"
some_class* myInstance = some_class_new();
int i = some_class_some_method(myInstance, 10.0f);
some_class_delete(myInstance);
Nếu bạn nghiêm túc về việc trộn C và C++, bạn sẽ muốn macro.
Dưới đây là một số mẫu vĩ mô của mà có thể làm này dễ dàng hơn nhiều:
// 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); }
Và vân vân. Tiêu đề/nguồn của chúng tôi trở thành:
// 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);
Và điều đó ngắn gọn hơn nhiều. Nó có thể được thực hiện đơn giản hơn (có thể) với vĩ mô variadic, nhưng đó là phi tiêu chuẩn và tôi để nó cho bạn. :] Ngoài ra, bạn có thể tạo macro cho các hàm không phải thành viên thông thường.
Lưu ý rằng C không không biết tham chiếu là gì. Nếu bạn muốn liên kết với một tham chiếu, đặt cược tốt nhất của bạn có thể chỉ để viết định nghĩa xuất khẩu theo cách thủ công. (Nhưng tôi sẽ suy nghĩ về nó, có lẽ chúng ta có thể tự động lấy nó).
Hãy tưởng tượng some_class
của chúng tôi đã tham chiếu float
bởi (không phải const) (vì bất kỳ lý do gì). Chúng tôi sẽ xác định chức năng như sau:
// 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);
}
Và ở đó chúng tôi đi. C sẽ giao diện với các tham chiếu có con trỏ thay thế:
// c source, if some_method took a reference:
float f = 10.0f;
int i = some_class_some_method(myInstance, &f);
Và chúng tôi vượt qua f
"theo tham chiếu".
Trong khi tôi không nói về extern "C", có rất nhiều thông tin liên quan trong bài đăng này về cách truy cập OO C++ apis từ C http://stackoverflow.com/questions/2045774/developing-c-wrapper-api -for-object-oriented-c-code/ –
@Peter: Tôi đã sửa chữa công cụ "C" bên ngoài. Trình biên dịch C không biết ý nghĩa của nó, vì vậy chúng ta tạo một macro biến thành 'extern" C "' trong C++ và không có gì trong C. Lý do chúng ta cần extern "C" là vì C++ mangles tên khi biên dịch. C không, do đó, bằng cách sử dụng 'extern" C "' chúng tôi cho trình biên dịch biết để cho điều này được biên dịch "C cách". – GManNickG