$ tree
.
|-- external.c
|-- sc.h
`-- serial_comm.cpp
$ cat external.c
#include "sc.h"
int main() {
struct MyStruct* sc;
sc->myFunction1();
}
$ cat sc.h
#ifndef SC_H
#define SC_H
struct MyStruct {
int myVariable;
void myFunction1();
void myFunction2();
};
#endif
$ cat serial_comm.cpp
#include <iostream>
#include "sc.h"
extern "C" void MyStruct::myFunction1() {
std::cout << "Function 1 called" << std::endl;
}
extern "C" void MyStruct::myFunction2() {
std::cout << "Function 2 called" << std::endl;
}
$ gcc external.c serial_comm.cpp -o my_program -lstdc++ -std=c++17
cc1: warning: command-line option '-std=c++17' is valid for C++/ObjC++ but not for C
In file included from external.c:1:
sc.h:6:10: error: field 'myFunction1' declared as a function
6 | void myFunction1();
| ^~~~~~~~~~~
sc.h:7:10: error: field 'myFunction2' declared as a function
7 | void myFunction2();
| ^~~~~~~~~~~
我现在有一个项目需要在C语言中调用C++17结构体的函数。我希望收到“已调用函数 1”。
我收到的错误消息如下。我应该如何纠正呢?谢谢。
编写一个C接口库。这种事经常做。
mylib.h
接口本身是用 C 和 C++ 编写的。这是因为它被 C(用于您想要使用库的所有 C 内容)和 C++(用于编译包装器库)使用。
#ifndef MYLIB_H
#define MYLIB_H
#ifdef __cplusplus__
extern "C" {
#endif
// Opaque structure type
typedef void mystruct;
mystruct * new_mystruct( int myVarInit );
void delete_mystruct( mystruct * );
int mystruct_getMyVar( mystruct * );
void mystruct_setMyVar( mystruct *, int );
void mystruct_myFunction( mystruct * );
#ifdef __cplusplus__
} // extern "C"
#endif
#endif
mylib-c-interface.cpp
这是包装纸。它被编译为 C++,但因为一切都是
extern "C"
,所以你可以与 C 代码链接。它所做的只是包装对 C++ 代码的调用。
#include "mylib.hpp" // the C++ header for your library
#include "mylib.h" // the C header for your library's C wrapper
mystruct * new_mystruct( int myVarInit )
try
{
mylib::mystruct * S = new mylib::mystruct( myVarInit );
return (mystruct *) S;
}
catch (...)
{
// Notice how we don't let exceptions escape the C++ side of things?
// Memory allocation failure is returned as a NULL pointer.
return nullptr;
}
void delete_mystruct( mystruct * S )
{
delete static_cast <mylib::mystruct *> (S);
}
int mystruct_getMyVar( mystruct * S )
{
return static_cast <mylib::mystruct *> (S)->myVar;
}
void mystruct_setMyVar( mystruct * S, int new_value )
{
static_cast <mylib::mystruct *> (S)->myVar = new_value;
}
void mystruct_myFunction( mystruct * S );
{
static_cast <mylib::mystruct *> (S)->myFunction();
}
您的 C 应用程序必须与 mylib
和
mylib-c-implementation
内容链接。它们不一定是独立的东西。您完全可以将 C 实现内容与 C++ 实现合并在同一个源文件中。如果您要编译为 DLL(或 SO),那么最好在 DLL 的符号表中简单地提供两边。
但是,如果您只想在链接到可执行文件之前编译为目标文件,那么您当然可以使用 #define 显式包含 C 内容(这样,如果不需要,它就不会出现在可执行文件中)。
但无论哪种方式,您都无法再仅使用一个命令行选项来快速轻松地进行编译。您需要将源文件单独编译为目标文件,然后将它们链接在一起以生成可执行文件(或 DLL)。
基本上就是这样!