从C DLL调用重载的C ++函数

时间:2014-06-06 16:10:32

标签: c++ c dll mingw overloading

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

由g ++(mingw32)生成的DLL与MSVC不兼容,__这个以及其他方式没有帮助。我的大部分代码都是用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 重载了三次。为了访问它,我在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 :) :)。

1 个答案:

答案 0 :(得分: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中,只需给它们不同的名称并拨打你想要的名称即可。