通过C++软件上的 C 接口传递/接收字符串

Passing/recieving strings through a C interface on a C++ software

本文关键字:字符串 接口 软件 C++ 通过      更新时间:2023-10-16

我不熟悉C,但我必须为我的C++软件编写一个C接口,以将其作为动态库提供。就经典实践而言,我有两个问题:

  1. 传递和接收字符串的经典方法是什么,谁负责内存?
  2. 始终保留错误代码的返回值,然后在参数中使用指针接收值是个好主意吗?如果没有,为什么?

这里有一个例子,用我首先想象的代码来说明我的问题:

int define_new_population(int* id)
{
// all_pop is a std::map<int,std::vector<boost::shared_ptr<Element>>>
*id = generate_id();
all_pop[*id] = std::vector<boost::shared_ptr<Element>>();
return 0;
}
int add_element_type1_in_pop(int pop_id, const char* name, double lower_bound, double upper_bound)
{
if(all_pop.find(pop_id) == all_pop.end())
return ERROR_CODE_WRONG_ID;
const std::string str_name(name);
try { all_pop[pop_id].push_back(boost::shared_ptr<Element>(new ElementType1(str_name, lower_bound, upper_bound))); }
catch(...) { return ERROR_CODE_FOO; }
return 0;
}
int add_element_type2_in_pop(int pop_id, const char* name, double reference)
{
if(all_pop.find(pop_id) == all_pop.end())
return ERROR_CODE_WRONG_ID;
const std::string str_name(name);
try { all_pop[pop_id].push_back(boost::shared_ptr<Element>(new ElementType2(str_name, reference))); }
catch(...) { return ERROR_CODE_BAR; }
return 0;
}
int get_population_size(int pop_id, int* pop_size)
{
if(all_pop.find(pop_id) == all_pop.end())
return ERROR_CODE_WRONG_ID;
*pop_size = (int)all_pop[pop_id].size();
return 0;
}
int get_element_name(int pop_id, int elem_index, char** name)
{
if(all_pop.find(pop_id) == all_pop.end())
return ERROR_CODE_WRONG_ID;
if(elem_index >= (int)all_pop[pop_id].size())
return ERROR_CODE_OUT_OF_RANGE;
const std::string& str_name = all_pop[pop_id][elem_index].getName();
*name = malloc(sizeof(char) * (str_name.length() + 1));
strcpy(*name, str_name.c_str());
return 0;
}

我至少可以给出一些建议。

  • 谁释放内存(调用方或 DLL(应在 API 中明确定义。
  • 请注意,如果调用方和被调用方使用不同版本的 Windows 标准 C 库单独编译,则不同版本的 C 库/运行时的 malloc 和 free 通常不起作用。如果您可以通过为 API 用户提供可与 RAII 一起使用的"内存释放"回调来自动执行此操作,那么这是一个好方法。给 API 用户提供简单的示例。
  • 如果您完全控制 DLL 库和调用方,您甚至可以通过 DLL 边界传递C++异常,这比错误代码干净得多,但如果您不知道自己到底做了什么,则更脆弱。
  • 你甚至可以有一个C++(不是纯C(api,使用window的/Visual Studio的"它只是工作"机制。它只是工作,甚至扩展到C++/CLI 和 C# 混合代码库。以下是更多文档:隐式 PInvoke

至于关于为错误代码保留返回值并发送指针(或在必要时发送指向指针的指针(的问题,这通常很好,并且是一种非常通用的技术。当然,如果您制作C++ API,现代方法是使用完美的转发和右值引用。