从 C++ => C 包装的 API(多线程)传输错误字符串
Transferring error strings from C++ => C wrapped API (multi-threaded)
我目前正在包装一个现有的C++库,以便在Go中使用。要做到这一点,我必须用C垫片包裹它,然后从Go访问它。当C++API引发异常,并且我当前正在使用errno
中的自定义值来传递错误条件时,我正在尝试找出一种方法来传递异常中的错误字符串。
我的绑定从C++API获取已分配的指针,并不透明地包装它们=>C=>Go。如果我编写了第三方库,我就可以将最后一个错误存储在类中,但显然我需要将其关联到其他地方。
因为Go/cgo是多线程的,所以我最初的想法是使用线程本地存储来存储错误字符串,并允许Go通过GetLastError()
函数获取它。我发现的问题是,在OSX上,没有线程本地存储(据我所知)。
免责声明:我的C/C++技能是新手
我如何从C++端的异常中获取错误字符串,并以特定于线程的方式存储它,使其可用于我的C包装器(即可用于go绑定),而不是在我的每个潜在错误函数中返回一个特殊的结构?或者,我唯一的选择真的是让我的所有C函数都使用输出参数和一个特殊的错误结构返回类型吗?
编辑:(从上下文对象的建议中提出的想法)
如果我的C++->C填充程序像这样包装类:
// foo.h
#ifdef __cplusplus
extern "C" {
#endif
typedef void Thing;
const char* Thing_foo(Thing *ptr);
#ifdef __cplusplus
}
#endif
#endif
// foo.cpp
extern "C" {
const char* Thing_foo(Thing *ptr) {
return static_cast<CPP::Thing*>(ptr)->foo();
}
}
使用同时携带指针和最后一条错误消息的struct Thing
,其效果是否与上下文基本相同?
typedef struct Thing {
void *ptr;
char *last_err;
} Thing;
您可以为使用上下文变量的C接口实现包装器。这样,您就可以将线程问题的控制权交给调用者。
这里有一个未经测试的例子:
包装纸.cpp
#include "wrapper.h"
struct context {
std::string last_error_message;
};
char const * ctx_get_last_error(context_handle ctx) {
if(ctx->last_error_message.empty()) return 0;
return ctx.last_error_message.c_str();
}
extern "C" context_handle create_context() {
return new context();
}
extern "C" void free_context(context_handle ctx) {
delete ctx;
}
extern "C" int my_lib_call(context_handle ctx, int some, char const * params) {
try {
lib_call(some, params);
}
catch(std::exception const & e) {
ctx->last_error_message = e.what();
return -1;
}
catch(...) {
ctx->last_error_message = "Unexpected error";
return -1;
}
return 0;
}
wrapper.h
#ifdef _cplusplus
extern "C" {
#endif
typedef struct context * context_handle;
context_handle create_context();
char const * ctx_get_last_error(context_handle ctx);
int my_lib_call(context_handle ctx, int some, char const * params);
#ifdef _cplusplus
}
#endif
如果您的平台都是POSIX平台,则可以使用pthread_[g|s]etspecific
来处理线程特定的数据。pthread_key_create上的opengroup页面包含如何使用此功能的示例。
如果可用(_Thread_local
是新的C和C++标准C11和C++11的一部分),您可以创建一个小型包装器库,该库使用线程本地变量,并在这些函数不可用时使用pthread函数作为后备。
AFAIR,windows有类似的功能,但我不是这方面的专家。
如果您真的不想传递额外的参数,您可能需要实现IPC(http://en.wikipedia.org/wiki/Inter-process_communication)像队列或命名管道这样的系统来传递您的数据。
- 在C++中使用cURL和多线程
- 多线程双缓冲区
- 为什么我的多线程作业队列崩溃
- 在main()之外初始化std::vector会导致性能下降(多线程)
- 试图创建一个多线程程序来查找0-100000000之间的总素数
- 为什么一个向量上的多线程操作很慢
- 学习多线程C++:添加线程不会使执行速度更快,即使它看起来应该
- 在 Win32 API 中使用多线程
- 按顺序保留多线程API的传入请求订单
- 从C API对python的多线程调用
- 如何使用QT/C 中的多线程用API访问我的数据库
- 使用C 中的Windows API使用多线程列出文件
- 从 C++ => C 包装的 API(多线程)传输错误字符串
- 使用Python和C api的多线程
- Log4cplus api在多线程环境下崩溃
- Win32 API多线程播放.wav文件没有延迟
- 图形时间线创建用于分析多线程c++程序的软件API
- 使用Win32 API在c++中使用多线程创建多个文件
- 嵌入式脚本语言与C/ c++ API多线程环境
- 使用C++API的多线程