我有一个函数类方法,ValueHolder :: printValue
class ValueHolder {
public:
void printValue ();
} ;
如何在编译时(或运行时)确定其损坏的名称。
例如,我想这样做:
const char *mangled_name = GetMangledNameOfSymbol(&ValueHolder::printValue);
此函数可能返回如下字符串:
"_ZN11ValueHolder10printValueEv"
根据@Marco A.先决条件是现代编译器。一个支持typeid,并打开标志以启用此功能。
我也会接受一个对Gcc& amp; Clang,以及MSVC的存根。
答案 0 :(得分:9)
根据[lib.type.info]
类type_info描述了实现生成的类型信息。此类的对象有效地存储指向该类型的名称的指针,以及适合于比较两种类型的相等或整理顺序的编码值。类型的名称,编码规则和整理顺序都是未指定的,程序之间可能有所不同。
并且对于您的编译器实现,您可以使用typeid(type/expression).name()
但是没有指定或强制执行此名称将被装饰(它是实现定义的)。它还取决于使用的编译标志(感谢malat)。
示例:
class ValueHolder {
public:
void printValue();
};
int main() {
std::cout << typeid(&ValueHolder::printValue).name();
}
gcc7.0
M11ValueHolderFvvE
clang4.0
M11ValueHolderFvvE
MSVC14
void(__ cdecl ValueHolder :: *)(void)__ ptr64
答案 1 :(得分:3)
我会添加一个答案,但我不会将其标记为正确。它不完整。太大了,无法添加评论。这是我能做的事情,但我正在寻找更好的方法。而且,是的,非常俗气的hacky。但我认为某些API虽然仍然有点严重,但仍可以保证工作(如果在整个项目中使用单个编译器)。
template<typename R, typename C, typename... A>
struct MemberFunctionPointer
{
typedef R Return;
typedef C Class;
};
template<typename R, typename C, typename... A>
constexpr auto inferMemberFunctionPointer(R (C::*method)(A...))
{
return MemberFunctionPointer<R,C,A...>{};
}
template<typename M, M m, typename... A>
class GenerateMethodSignature
{
typedef typename decltype(inferMemberFunctionPointer(m))::Class T;
typedef typename decltype(inferMemberFunctionPointer(m))::Return R;
public:
static const char *mangledName (const char *fs)
{
const char *ts = typeid(T).name();
const char *rs = typeid(R).name();
const char *ms = typeid(M).name();
std::string r = "_Z";
if (ts[0] != 'N')
r += "N";
r += ts;
if (ts[0] == 'N')
r.pop_back();
r += std::to_string(strlen(fs));
r += fs;
r += "E";
r += ms + strlen ("M") + strlen(ts) + strlen ("F") + strlen(rs);
r.pop_back();
printf("calculated signature %s\n", r.c_str());
// this is very bad but... for demonstration purposes
return strdup(r.c_str());
}
} ;
namespace MyNamespace {
namespace MySubNamespace {
class MyClass
{
public:
int MyFunction (int myarg);
} ;
} // namespace
} // namespace
#define ExportSignature(T, M) GenerateMethodSignature<decltype(&T::M), &T::M>::mangledName(#M)
const char *myMethodSignature = ExportSignature(MyNamespace::MySubNamespace::MyClass, MyFunction);
答案 2 :(得分:-2)
你能做的就是使用g ++编译你的C ++程序并获取.o文件。在如此获得的.o文件上运行'nm'命令以获取受损的名称!这种方法在Linux系统上是可行的。