简体   繁体   中英

Calling overloaded C++ functions from C DLL

There is an application (Proteus VSM), written in MSVC C++ that supports DLL based plugins.

DLL produced by g++ (mingw32) is not compatible with MSVC, __thiscall and other way is not helpful.Most of my code is written in gcc/mingw and have a lot of GAS-based assembly parts (not for speed up) etc, so it very hard to rewrite it just for Windows DLL project (other code is for Linux)

Here is original header from 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; 
};

As you can see, function setstate is overloaded three times. In order to access it, I did the following in 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;

};

Now I can access this functions like this:

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

This works ok for "normal" functions. But when it comes to setstate , for example, it works not as expected. As I cannot use overloaded functions in C, I tried with one of them at once. Only VOID "version" works as expected, the others behaves in wrong manner.

I'm not sure this is the root cause of the problem and I understand that it is probably weird programming at all, but may be someone can help me with possible workaround (except porting code to MSVC :) ).

Each overload has a pointer in the 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);
};

In C, simply give them different names and call the one you want.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM