python和c++中高效的DRY双向查找



在我们的工作流程中,我们有几个整数ID <->字符串名称映射(例如,状态/错误代码,硬件id等)。我们正在努力寻找在c++和python中为这些值编写双向查找库的最佳方法。

接口可能看起来像


namespace myproject{
namespace lookup{
typedef long ID_t;
enum class STATUSCODE :ID_t {OK=0, ERROR=1, UNKNOWN=-1}; 
std::string GetStatusDescription(ID_t statuscode);
ID_t GetStatusCode(const std::string& statusdesc);
enum class DEVICELABEL :ID_t {SuperThing_v1=0x234, LessSuperThing_v12=0x12};
std::string GetDeviceLabel(ID_t hardwareid);
ID_t GetHardwareID(const std::string& devicelabel); 
}
}
#file myproject/lookup.py
class STATUSCODE(Enum):
OK=0
ERROR=1
UNKNOWN=-1
def GetStatusDescription(statuscode: int) -> str:
pass
def GetStatusCode(statusdesc: str) -> int:
pass

class DEVICELABEL(Enum):
SuperThing_v1=0x234 
LessSuperThing_v12=0x12
def GetDeviceLabel(hardwareid: int) -> str:
pass
def GetHardwareID(devicelabel: str) -> int:
pass

理想情况下,实现将满足以下所有条件:

  • 实际的表位于单个文件中(或每个表一个文件,但不像上面示例中的枚举那样重复)
  • 为整数、字符串和枚举输入提供高效的双向查找。例如,python的Enum类是理想的。在c++方面,我认为我们仍然被用于枚举<->字符串映射的预处理器技巧所困扰。枚举接口很好,但不是必需的。
  • c++接口应该在编译时读取表,以避免不得不定位数据文件

查找表都很小,并且极不可能增长到我们必须担心驻留在内存中的程度。我们真的只关心找到一个好的DRY方式来存储和读取信息。我希望能够找到一种方法来格式化数据表,以便它可以被python和c++编译器解析(可能在一些预处理器宏的帮助下)。我们团队中没有人有为C函数创建python绑定或其他方式的经验,所以我们希望尽可能避免这种方式。但是,如果这真的是最好的方法,我将非常感谢您提供关于如何最好地实现它(swig, boost::python?)的建议。

在其他SO答案中已经讨论了两个方法:

  • python和arduino之间的共享enum:从Python

    写入C文件
  • Python可以从C头文件加载定义吗?解析C文件创建Python值

无需处理,只需共享公共文件即可:shared.py

#define my_table const struct entry my_table[]
#define statement_end() ;
#define frozenset(...) __VA_ARGS__
#if 0
def statement_end():
return
#endif
my_table = {frozenset({"OK" , 0}), frozenset({"ERROR", 1}), frozenset({"UNKNOWN", -1})}
statement_end()
#undef my_table
#undef statement_end
#undef frozenset

当与Python一起使用shared.py时,所有以#开头的行都会被忽略,因为它们是Python注释。当它与C一起使用时,#if 0中的Python代码被忽略,#define语句生效

c

#include <stdio.h>
struct entry {
char *str;
int n;
};
#include "shared.py"
int main()
{
/*
* Write here great code that create bi directional lookup
* from array of entry struct.
* Ideas can be taken from https://stackoverflow.com/questions/6669842/how-to-best-achieve-string-to-number-mapping-in-a-c-program
*/

for (const struct entry * pair = my_table; (char *)pair != (char *)my_table + sizeof(my_table); pair++)
{
printf("str: %s. int: %dn", pair->str, pair->n);
}
return 0;
}

main.py

import shared
# Write here great code that create bi directional lookup from set of frozensets, each one contain int and string
for pair in shared.my_table:
print(pair)