如何在c中调用c++结构体函数?

问题描述 投票:0回答:1
$ 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++ c c++17
1个回答
0
投票

编写一个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)。

基本上就是这样!

© www.soinside.com 2019 - 2024. All rights reserved.