如何在C代码中访问C ++结构的std :: string成员

时间:2019-05-02 16:37:32

标签: c++ c

假设我混合使用C ++和C代码。在C ++代码内部,我在my_cpp_code.h中有一个结构:

typedef struct {
    std::string some_string;
    int some_int;
    bool some_bool;
} CppStruct;

具有另一个源文件,例如C my_c_code.c。是否可以以some_string的身份访问此文件中结构的const char *成员?

4 个答案:

答案 0 :(得分:4)

C编译器无法理解CppStruct的定义。所以不,C程序无法访问CppStruct::some_string但是,您可以提供一组C ++函数,这些函数公开与C兼容的签名,以便从CppStruct::some_string进行读写。

// === compat.h ===
struct CppStruct;
#ifdef __cplusplus
extern "C" {
#endif
    CppStruct* get_the_damn_struct();
    int set_some_string(CppStruct*, char* data, size_t len);
    int get_some_string(CppStruct*, char* data, size_t* len);
#ifdef __cplusplus
}
#endif

// === compat.cpp ===
// Implementation

// === c_program.c ===
#include <compat.h>

// usage (e.g.:
CppStruct* wrapper = get_the_damn_struct();
char* data = "Hello, World!";
if (0 != set_some_string(wrapper, data, strlen(data)) {
    // error handling
}
//)

答案 1 :(得分:3)

不是直接否。

一种解决方案是在C语言端使用不透明的指针(有点像FILE*),然后将其传递给在C ++端实现的函数(并使用C链接进行编译:有关如何执行此操作的编译器文档)。该函数可以具有const char*返回类型,因为C和C ++都可以理解。然后,该函数可以reintepret_cast将该不透明指针(例如,p指向您的struct的实例,然后返回p->some_string.c_str()

答案 2 :(得分:2)

您可以有一个C ++函数返回一个指向这样的结构对象的指针,但仍为void*,并且您可以有另一个C ++函数将这样的void*指针指向结构对象。并且-在将其回退之后-访问成员的c_str函数。在单独的头文件(不与C ++代码混合)中将这些函数声明为纯C函数:

示例:

// my_cpp_bridge.h:
void* getAStructPtr();
const char* getStringMemberPtr(void* structPtr);

// my_cpp_bridge.cpp:
#include "my_cpp_code.h"
#include "my_cpp_bridge.h"
void* getAStructPtr() {
   static CppStruct someSample;
   someSample.some_string = "Hello world!";
   return (void*)&someSample;
}
const char* getStringMemberPtr(void* structPtr) {
   const CppStruct *structPtr = reinterpret_cast<CppStruct*>(structPtr);
   return structPtr->c_str();
}

// my_test.c:
#include "my_cpp_bridge.h"
int main() {
   void* s = getAStructPtr();
   const char* content = s->getStringMemberPtr();
}

答案 3 :(得分:0)

您的问题可能是“ XY问题”(您问问题“ X”,但如果您只知道这可能是一个更好的选择,则最好问“ Y”)。此答案提出了一个替代方案,从技术上讲它不会回答您提出的问题,但可以解决提示该问题的问题:

将您的旧版C代码编译为C ++,这甚至不是问题。

如果您必须将C代码保持纯C,那么您正在寻找其他答案。但是,如果像我一样,您正在使用旧的C代码和新的C ++代码混合的项目,那么也许您应该开始将旧的代码从纯C移开。当然,如果您需要保持旧的代码“纯净” C”,因为它与仍编译为严格C的单独项目共享,因此这不是一个选择,但让我们假设这不是必需的。我现在已经在两个大型固件项目上完成了两次,效果很好。

如果将C代码编译为C ++,那么即使在旧的“ C”代码中,您也可以开始利用C ++功能。一种方法是找到将C视为C ++代码的编译器选项。例如Visual Studio的/ TP选项(有关更多信息,请参见this SO post)。对于GCC,将您的makefile更改为使用g ++。或者,如果没有此类选项,请使用.cpp扩展名重命名.c文件。

一旦您将C代码编译为C ++,您可能会遇到其他较小的问题,但是这些问题并不太难解决,并且长期收益将超过最初的麻烦。有关更多信息,请参见this SO post。也许主要的问题是,如果您使用malloc(),则需要在将返回值分配给类型化的指针之前进行类型转换。

一旦将遗留代码编译为C ++,那么您就可以在遗留代码中完成所有工作,就像在新C ++代码中可以做到的那样,因此,原来的问题所引起的问题根本不再是问题。您pip在C文件中,然后在需要原始pip install django --force 指针时随时调用#include <string>(例如,调用其他带有myCppStruct.some_string.c_str()参数的旧版C函数)。无需实用程序功能即可为您完成。