假设我混合使用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 *
成员?
答案 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 ++代码的编译器选项。例如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函数)。无需实用程序功能即可为您完成。