简体   繁体   English

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

[英]How to access an std::string member of C++ struct in C code

Suppose I have mixed C++ and C code. 假设我混合了C ++和C代码。 Inside the C++ code, I have a struct in my_cpp_code.h : 在C ++代码中,我在my_cpp_code.h有一个结构:

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

Having another source file, say C my_c_code.c . 有另一个源文件,比如C my_c_code.c Is it possible to access the some_string member of the struct in this file as a const char * ? 是否可以作为const char *访问此文件中struct的some_string成员?

AC compiler wouldn't understand the definition of CppStruct . AC编译器无法理解CppStruct的定义。 So no, it is not possible for a C program to access CppStruct::some_string . 所以不,C程序不可能访问CppStruct::some_string But you can provide a set of C++ functions exposing a C-compatible signature to read/write from/to 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
}
//)

Not directly no. 不是直接没有。

One solution would be to have an opaque pointer on the C language side (a bit like FILE* ), that you pass to a function which is implemented on the C++ side (and is compiled with C linkage: consult your compiler documentation on how to do that). 一种解决方案是在C语言端有一个不透明的指针(有点像FILE* ),你传递给在C ++端实现的函数(并使用C链接编译:请参阅编译器文档,了解如何去做)。 That function can have a const char* return type since both C and C++ understand that. 该函数可以有一个const char*返回类型,因为C和C ++都能理解这一点。 That function can then reintepret_cast that opaque pointer ( p , say) to an instance of your struct , then return p->some_string.c_str() back. 这个函数可以再reintepret_cast是不透明的指针( p ,说)你的实例struct ,然后返回p->some_string.c_str()回来。

You can have one C++ function that returns a pointer to such a struct-object, yet as void* , and you can have another C++ function that takes such a void* -pointer to a struct object and - after having casted it back - accesses the member's c_str -function. 你可以有一个C ++函数,它返回一个指向这样一个struct-object的指针,但是作为void* ,你可以有另一个C ++函数,它将一个void* -pointer带到一个struct对象,并且 - 在将它转换回来之后 - 访问成员的c_str -function。 Declare these functions a pure C-functions in a separate header file (not mixed with C++ code): 在单独的头文件中声明这些函数是纯C函数(不与C ++代码混合):

Example: 例:

// 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();
}

Your question might be an "XY problem" (you ask question 'X' but really you'd do better to ask 'Y' if only you knew it might be a better option). 你的问题可能是一个“XY问题”(你问问题'X',但如果你知道它可能是一个更好的选择,你真的会更好地问'Y'。 This answer poses an alternative that technically doesn't answer the question that you asked, but it can solve the problem that prompted the question: 这个答案提出了一个替代方案,从技术上讲,它没有回答你提出的问题,但它可以解决引发问题的问题:

Compile your legacy C code as C++ and this isn't even an issue. 将您的旧C代码编译为C ++,这甚至都不是问题。

If you must keep your C code pure C, then any of the other answers are what you're looking for. 如果你必须保持你的C代码纯C,那么任何其他答案都是你正在寻找的。 But if, like me, you're working on a project that uses legacy C code mixed with new C++ code, then perhaps you should start moving the legacy code away from pure C. Of course if you need to keep the legacy code "pure C" because it's shared with a separate project that's still compiled as strict C then this isn't an option, but let's suppose that's not a requirement. 但是,如果像我一样,你正在开发一个使用传统C代码与新C ++代码混合的项目,那么也许你应该开始将遗留代码从纯C中移开。当然,如果你需要保持遗留代码“纯粹” C“因为它与一个仍然编译为严格C的单独项目共享,那么这不是一个选项,但我们假设这不是一个要求。 I've done this twice now on two large firmware projects with excellent results. 我已经在两个大型固件项目中完成了两次,效果非常好。

If you compile your C code as C++, then you can start to take advantage of C++ features even in your legacy "C" code. 如果将C代码编译为C ++,那么即使在旧的“C”代码中也可以开始利用C ++特性。 One way to do that is to find a compiler option to treat C as C++ code; 一种方法是找到一个编译器选项来将C视为C ++代码; eg Visual Studio's /TP option (see this SO post for more info). 例如Visual Studio的/ TP选项(有关详细信息,请参阅此SO帖子 )。 For GCC, change your makefile to use g++. 对于GCC,将makefile更改为使用g ++。 Or, if there is no such option, rename your .c files with .cpp extensions. 或者,如果没有此选项,请使用.cpp扩展名重命名.c文件。

Once you're compiling C code as C++, you may run into other minor problems, but those shouldn't be too difficult to work through, and the long-term benefits will outweigh the initial hassle. 一旦你将C代码编译为C ++,你可能会遇到其他一些小问题,但这些问题不应该太难解决,长期的好处将超过最初的麻烦。 See this SO post for more information about that. 有关详细信息,请参阅此SO帖子 Perhaps the main issue is that if you use malloc(), you will need to typecast the return value before assigning it to a typed pointer. 也许主要的问题是,如果使用malloc(),则需要在将返回值分配给类型指针之前对其进行类型转换。

Once you're compiling your legacy code as C++, then you can do everything in your legacy code that you can do in your new C++ code, so the issue posed by your original question is no longer an issue at all. 一旦您将遗留代码编译为C ++,那么您可以在遗留代码中执行可以在新C ++代码中执行的所有操作,因此原始问题所带来的问题根本不再是问题。 You #include <string> in your C file and then just call myCppStruct.some_string.c_str() any time you need a raw const char* pointer (eg to call other legacy C functions that take const char* parameters). 您需要在C文件中#include <string> ,然后在需要原始const char*指针时调用myCppStruct.some_string.c_str() (例如,调用其他带有const char*参数的传统C函数)。 No need for a utility function to do it for you. 不需要实用程序功能来为您完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM