【问题标题】:Calling overloaded C++ functions from C DLL从 C DLL 调用重载的 C++ 函数
【发布时间】:2014-06-06 16:10:32
【问题描述】:

有一个应用程序 (Proteus VSM),用 MSVC C++ 编写,支持基于 DLL 的插件。

g++ (mingw32) 生成的 DLL 不兼容 MSVC,__thiscall 和其他方式没有帮助。我的大部分代码都是用 gcc/mingw 编写的,并且有很多基于 GAS 的组装部分(不是为了加速)等等,所以很难仅仅为 Windows DLL 项目重写它(其他代码是用于 Linux)

这是来自 SDK 的原始标头:

class IDSIMPIN1
{ public:
  virtual EVENT *setstate (ABSTIME time, RELTIME tlh, RELTIME thl, RELTIME tgq, STATE state) = 0;
  virtual EVENT *setstate (ABSTIME time, RELTIME tgq, STATE state) = 0;
  virtual VOID setstate (STATE state) = 0;
  virtual VOID sethandler (IDSIMMODEL *model, PINHANDLERFN phf) = 0;
  virtual DSIMNODE getnode() = 0;
  virtual STATE getstate() = 0; 
};

如您所见,函数 setstate 被重载了 3 次。为了访问它,我在 C 中做了以下操作:

#define __thiscall __attribute__((fastcall))
#define EDX DWORD EDX
typedef struct IDSIMPIN1 IDSIMPIN1;
typedef struct IDSIMPIN1_vtable IDSIMPIN1_vtable;

struct IDSIMPIN1_vtable
{
    //EVENT* __thiscall (*setstate)(IDSIMPIN1 *this, EDX, ABSTIME time, RELTIME tgq, STATE state);  
    VOID __thiscall (*setstate)(IDSIMPIN1 *this, EDX, STATE state);
    VOID __thiscall (*sethandler)(IDSIMPIN1 *this, EDX, IDSIMMODEL *model, PINHANDLERFN phf);
    DSIMNODE __thiscall (*getnode)(IDSIMPIN1 *this, EDX);
    STATE __thiscall (*getstate)(IDSIMPIN1 *this, EDX);
};

struct IDSIMPIN1
{

    IDSIMPIN1_vtable *vtable;

};

现在我可以像这样访问这些函数了:

IDSIMPIN1 *pin;
...
pin->vtable->setstate(pin, 0, SHI);

这适用于“正常”功能。但是当涉及到 setstate 时,例如,它的工作方式与预期不同。因为我不能在 C 中使用重载函数,所以我一次尝试了其中一个。只有 VOID“版本”按预期工作,其他的行为错误。

我不确定这是问题的根本原因,并且我知道这可能是一种奇怪的编程,但可能有人可以帮助我解决可能的解决方法(将代码移植到 MSVC :) 除外。

【问题讨论】:

  • 您意识到每个重载都会在 vtable 中拥有自己的条目吗?
  • 是的,但是有没有办法限制它使用特定的?
  • 有所有的指针并且只调用那个?
  • 你能举例说明一下吗?

标签: c++ c dll mingw overloading


【解决方案1】:

每个重载在 vtable 中都有一个指针:

struct IDSIMPIN1_vtable
{
    EVENT* __thiscall (*setstate1)(IDSIMPIN1 *, ABSTIME, RELTIME, RELTIME, RELTIME, STATE);
    EVENT* __thiscall (*setstate2)(IDSIMPIN1 *, ABSTIME, RELTIME, STATE);
    VOID __thiscall (*setstate3)(IDSIMPIN1 *, STATE);
    VOID __thiscall (*sethandler)(IDSIMPIN1 *this, EDX, IDSIMMODEL *model, PINHANDLERFN phf);
    DSIMNODE __thiscall (*getnode)(IDSIMPIN1 *this, EDX);
    STATE __thiscall (*getstate)(IDSIMPIN1 *this, EDX);
};

在 C 中,只需给它们起不同的名称,然后调用你想要的名称。

【讨论】:

  • 天哪,这么简单。非常感谢!看来我不太了解 vtable 的工作原理
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多