c++ - 如何在 C++ 中创建一个可以从 C 代码全局引用的对象?
问题描述
我有一个 C 语言的大型程序,我想将某些 C++ 对象与地图等一起使用。我关注了这篇关于如何从 C 调用 C++ 的帖子,我的两个 C++ 看起来像这样。
///map.cc
#include "map.h"
void* createMap()
{
std::map<int,int> *m = new std::map<int,int>();
return static_cast<void*>(m);
}
void putInMap(int key, int value, void* opaque_map_ptr){
std::map<int,int> *m = static_cast<std::map<int,int>*>(opaque_map_ptr);
m->insert(std::pair<int,int>(key,value));
}
//map.h
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
EXTERNC void* createMap();
EXTERNC void putInMap(int key, int value, void* opaque_map_ptr);
我不清楚的是,如果我在我的 C 程序中执行以下调用,我如何确定我的 Map 存在以及如何使其成为全球性的?我是否只是将相应的指针设为全局?
#include "map.h"
//How do I let everyone use this map
void* ptr = createMap();
解决方案
//How do I let everyone use this pointer void* ptr = createMap();
不是通过使用初始化程序声明一个全局对象= createMap()
. C 不允许 C++ 具有的那种全局变量的动态初始化。指针必须由常量表达式初始化。如果你想createMap()
在 C 中调用它只能在main
输入之后发生,并且函数调用是显式的。
通常的模式是提供一个执行延迟初始化并返回指针的函数。
void *globalMap() {
static void *ptr = NULL;
if (!ptr)
ptr = createMap();
return ptr;
}
然后可以使用调用代码globalMap()
来获取指向该对象的共享指针。如果需要“类对象”语法,则可以使用宏来包装函数调用
#define globalPtr globalMap()
这方面的一个标准示例可以通过errno
.
必须提到的另一件事是我写了一个非常幼稚globalMap()
的,因为指针分配不是线程安全的。使其线程安全并非不可能,但代码会稍微复杂一些。您可以由 C++ 编译器隐式完成(C++11 及更高版本)。该技术是所谓的 Meyers Singleton
extern "C" void *globalMap() {
static std::map<int, bool> m;
return &m;
}
就是这样。C++ 编译器将对其进行检测,使其m
仅初始化一次并且没有竞争条件。
最后一点,不要忘记您必须在 ABI 边界上处理 C++ 异常!在正确的位置使用一些说明符使它们全部致命noexcept
是一种方法,或者将它们转换为可能返回到 C 代码进行检查的错误。无论哪种方式,都不要忽视它们的存在。
推荐阅读
- javascript - 使用 Angular8 中的 API 验证令牌 canActivate AuthGuard 方法
- powerbi - power bi 桌面中 dax 测量的总计错误
- android - 点击图片并带上 ViewPager
- java - 流已被操作或关闭,尝试创建 Racers 时出现异常
- excel - 从 excel 运行 MS Word 邮件合并
- c# - 一个 Web 应用程序和工作两个地址 URL
- angular - Include a specific file in prod ng build
- html - 从浏览器请求 .html 页面时出现 IIS 10 错误(指定的 CGI 应用程序遇到错误)
- sql - 如何使用其他列查询聚合数据
- r - 根据值绘制一个仅行和仅点的变量