在运行时从字符串处理MSVC C ++名称

时间:2019-03-14 09:52:23

标签: c++ visual-studio name-mangling

首先,我将从需要在运行时修改名称的原因开始。

我需要在dll及其包装程序之间建立一座桥梁

const asyncForEach = async function (array, callback) {
  for (let index = 0; index < array.length; index++) {
    await callback(array[index], index, array)
  }
}

const asyncLoop = async () => {
  const measurements: { name: string, station: string, data: any[] }[] = [];
  try {
    await asyncForEach(selectedTracks, async selectedTrack => {
      await asyncForEach(selectedTrack.tcIDs, async trackCircuitId => {
        await this.props.loadMeasurements(dateFrom, dateTo, trackCircuitId, selectedTrack.station);
        console.log(this.props.measurements) // If it works well
        measurements.push({
          name: trackCircuitId,
          station: selectedTrack.station,
          data: this.props.measurements
        });
      })
    })

    this.setState({
      measurements,
      refresh: false
    });
  } catch (err) {
    console.log(err)
  }
}

asyncLoop()

这个想法是使用dumpin生成包含类令牌的dll的所有损坏的名称,然后将它们分解。

?release @ Token @@ UAEXXZ->无效Token :: release(void)

之后我要转换的是匹配包装器,因此我需要更改函数名称

void Token :: release(void)-> void Wrapper :: Token :: release(void)

然后我需要再次处理它,以便可以创建一个将旧功能定向到新功能的def文件。

?release @ Token @@ UAEXXZ =?release @ Token @ Wrapper @@ UAEXXZ

所有这些过程都需要在运行时进行。

第一个也是最简单的解决方案是找到一个处理字符串的函数,但是我找不到任何...

还有其他解决方案吗?

2 个答案:

答案 0 :(得分:2)

Clang编译器与MSVC兼容ABI,包括名称修改。 基础基础结构是LLVM项目的一部分,我发现llvm-undname可以使MSVC名称分解。也许您可以对其进行重做,以将Wrapper::名称空间添加到符号中并进行重新组合。

您可以在this test code中找到有关修改名称的灵感。

答案 1 :(得分:0)

如果允许您更改DLL,我通常会使用不同的方法,方法是导出extern“ C” getter函数(该函数不会发生混乱,因此不需要分解)并使用虚拟接口访问该类(请注意,然后不需要dllexport虚拟接口)。无论如何,您的令牌界面似乎都是虚拟的。

沿着这些思路的东西(未经测试,只是为了展示这个想法):

DLL访问标头:

class Token  // notice no dllexport!
{
protected:
    // should not be used to delete directly (DLL vs EXE heap issues)
    virtual ~Token() {}
    virtual void destroyImpl() = 0; // pure virtual
public:
    static inline void destroy(Token* token) {
        // need to check for NULL otherwise virtual call would segfault
        if (token) token->destroyImpl();
    }
    virtual void doSomething() = 0; // pure virtual
};

extern "C" __declspec(dllexport) Token * createToken();

DLL的实现:

class TokenImpl: public Token
{
public:
    virtual void destroyImpl() {
        delete this;
    }
    virtual void doSomething() {
        // implement here
    }
};

extern "C" __declspec(dllexport) Token * createToken()
{
    return new TokenImpl;
}

用法:

// ideally wrap in RAII to be sure to always release
// (e.g. can use std::shared_ptr with custom deleter)
Token * token = createToken();

// use the token
token->doSomething();

// destroy
Token::destroy(token);

使用shared :: ptr(还可以在Token接口中创建typedef / static内联便捷创建器函数):

std::shared_ptr<Token> token(createToken(),
                             // Use the custom destroy function
                             &Token::destroy);
token->doSomething()
// token->destroy() called automatically when last shared ptr reference removed

这样,您只需要导出extern-C创建者函数(以及释放函数,如果不是接口的一部分),该函数就不会被破坏,因此易于通过运行时加载来使用。