简体   繁体   中英

How can I call a __thiscall from C?

I'm writing something in C that will be running in the context of an application written in C++ and i would like to call some of the application's functions that use calling conventions unsupported by C. Is there any way I could do this? I'm willing to get my hands dirty with the inline assembler.

I have the prototype and address of the function I want to call, but I can't implement the prototype in C because it is a __thiscall. Would something like

__asm
{
    push ecx
    mov ecx, this
}
ThiscallFunction(...);
__asm
{
    pop ecx
}

work, given I use the same function prototype but a __stdcall for ThiscallFunction()?

I have done this in the past calling methods of a class from a separate module. This depends on which OS you're on when using X64 but on x86 it follows similar to the cdecl calling convention only the 'this' pointer is passed in ecx. The rest of the arguments are passed on the stack from right to left.

Essentially in order to perform a this call you'd need the instance pointer and the function address. It would look similar to this

class T{
    int x;
    T(){
        x = 0;
    }
    int getx(){
        return x;
    }
};
__declspec(naked) int thisgetx(void* instance, void* address){
    mov ecx,[esp+4]
    mov eax,[esp+8]
    add esp,8
    call eax
    ret
}

This is assuming you're using Microsoft's C compiler. You'd need the naked attribute if using gcc/clang

The exact solution depends on the problem, but generally, you will need a header file specifying the interface towards the C code. This header file should be understandable for both the C and C++ parts.

Eg (common C/C++ header file):

...
#ifdef __cplusplus
extern "C" {
#endif

void draw_shape(void *shape_handle, double scale);
...

#ifdef __cplusplus
}
#endif

Furthermore, it is necessary to make wrapper functions in the C++ code for C++ functions with a prototype that is incompatible with C (eg having a std::string parameter or being a class member function).

Eg (C++ class member function wrapper implementation):

void draw_shape(void *shape_handle, double scale)
{
    static_cast<Shape *>(shape_handle)->draw(scale);
}

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