Существует приложение (Proteus VSM), написанное в MSVC C++, которое поддерживает плагины на основе DLL.
DLL, созданная g++ (mingw32), несовместима с 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 перегружается три раза. Чтобы получить доступ к нему, я сделал следующее в 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:
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 просто дайте им разные имена и вызовите тот, который вы хотите.