我正在为一个内部项目设计下一代的框架架构。本质上,有一个运行时系统,它为可以动态加载/卸载的应用程序提供API。
在框架中有一个自定义“设备”库,这些设备的当前接口非常通用;例如posix加载/卸载/读/写/等等。该框架的重要原则之一是,应用程序需要很少了解设备的细节。
不幸的是,这个接口已经分解为应用程序开发人员重写应用程序本身中的通用函数的地方。
我正在寻找一些建议,甚至是开始阅读像这样的框架API设计的地方。框架中的“设备”作者可以使用什么好的工具来发布接口?发布接口的最佳方法是什么?
发布于 2014-03-06 21:41:08
好的--一个建议--可能和你想要的有很大不同,但是反馈会帮助你了解一些有用的东西。
对于同步“调用”,您希望您的应用程序模块发送所需的驱动程序函数的指示,无论参数是多少,然后检索一些结果。这可以通过具有第二种不同的读/写流来实现,在此流上传输函数和值的编码。因此,假设驱动程序API包括:
string get_stuff(string x, int y, double d[]);这不是代码-它是框架/应用程序可以打印/解析的文本,并可能用于验证数据是否相应地发送和使用。
然后,app模块将对驱动程序的“调用”写成函数标识符和输入流,然后读取结果(假设app模块有相同名称的变量,保存所需的参数值)。
driver_api << "get_stuff " << escape(x) << ' ' << y << " [" << d.size() << "] ";
for (auto i = d.begin(); i != d.end(); ++i)
driver_api << ' ' << *i;
driver_api << '\n';
std::getline(driver_api, result);工作还多一点(半小时?)要创建一个自定义流包装器,它可以包装driver_api并插入上面的空格或其他分隔符/分隔符,支持容器流,并/或以二进制形式发送数据,使您可以编写更干净和/或更快的面向值的上述版本,如下所示:
(driver_api << "get_stuff" << x << y << d) >> result;您还可以编写普通的C++函数来包装上面的内容,以便app模块调用:
string get_stuff(const std::string& x, int y, const std::vector<double>& d)
{
string result;
(driver_api_ << "get_stuff" << x << y << d) >> result;
return result;
}在驱动端,您可以编写匹配的反序列化例程来从流中恢复应用模块指定的值。
对于特定的体系结构,您可以获得库,以允许更方便地调用函数、使用调试信息或ABI知识等,而上面只需要标准C++,并且可以编写为可移植(如果对endian值进行二进制序列化时要小心)。
编辑-二进制序列化的示例(现在只是输出/运行,但是输出没有仔细检查有效性/大多数事情都是固定宽度的,但是字符串以NUL结尾,容器以大小作为前缀/不发送以下字段类型的信息,但是很容易创建一个版本):
#include <iostream>
#include <vector>
#include <winsock2.h>
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned uint32_t;
class Binary_IOStream
{
public:
Binary_IOStream(std::istream& i, std::ostream& s) : i_(i), s_(s) { }
typedef Binary_IOStream This;
This& operator<<(int8_t x) { return write(x); }
This& operator<<(int16_t x) { return write(htons(x)); }
This& operator<<(int32_t x) { return write(htonl(x)); }
This& operator<<(uint8_t x) { return write(x); }
This& operator<<(uint16_t x) { return write(htons(x)); }
This& operator<<(uint32_t x) { return write(htonl(x)); }
This& operator<<(const std::string& s)
{ s_.write(s.c_str(), s.size() + 1); // include NUL, but could size-prefix
return *this; }
This& operator<<(double x) { return write(x); }
template <typename T>
This& operator<<(const std::vector<T>& v)
{ return write_range(v.begin(), v.end()); }
template <typename Iterator>
This& write_range(Iterator begin, Iterator end)
{
operator<<(std::distance(begin, end));
while (begin != end)
operator<<(*begin++);
return *this;
}
private:
template <typename T>
This& write(const T& t)
{ s_.write((const char*)&t, sizeof t); return *this; }
std::istream& i_;
std::ostream& s_;
};
int main()
{
Binary_IOStream bs(std::cin, std::cout);
bs << ('A' << 24) + ('b' << 16) + ('c' << 8) + 'D';
bs << "hello world!";
std::vector<double> v;
v.push_back(3.14);
v.push_back(2.72);
bs << v;
}https://stackoverflow.com/questions/22234360
复制相似问题