[英]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:
这个答案提出了一个替代方案,从技术上讲,它没有回答你提出的问题,但它可以解决引发问题的问题:
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.