程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> C語言函數動態調用(參考UnderC實現)

C語言函數動態調用(參考UnderC實現)

編輯:關於C

 

#include "stdafx.h"

#include <stdarg.h>

#include <windows.h>

#include <locale.h>

#include <stdlib.h>

 

 

const int DC_STADCALL = 0, DC_CDECL = 1, DC_QWORD = 2, DC_NOWORD = 4, DC_RET_OBJ = 8, DC_RET_VAL = 16 + 8;  

void *gObjectReturnPtr = NULL; // 沒有用的

 

void callfn(void* fn, int args[], int argc, void *optr, int flags, void *buff)

{

   int sz = sizeof(int)*argc;

  _asm {

    mov ecx, argc

    mov ebx, args

    // push the arguments onto the stack, backwards

a_loop:

    cmp ecx,0

    jz a_out

    mov eax, [ebx + 4*ecx]

    push eax

    dec ecx

    jmp a_loop

 

a_out:

    mov ecx,optr // thiscall calling convention (MS only)

    call fn

    // Cleanup stack ptr if this was a cdecl call

    mov ecx, flags

    test ecx,DC_CDECL

    jz  a_over

    add  esp,sz

a_over:

    test ecx,DC_RET_OBJ

    jz a_again

// these cases are peculiar to GCC

    cmp ecx,DC_RET_VAL

    jl  a_skip

    mov ebx, gObjectReturnPtr

    mov [ebx],eax

    mov [ebx+4],edx

    jmp a_finish

a_skip:

sub  esp,4

a_again:

    mov ebx,buff

    test ecx,DC_QWORD

    jnz  a_dbl

    mov  dword ptr[ebx],eax

    jmp a_finish

a_dbl:

    fstp qword ptr[ebx]

a_finish:

  }

}

 

 

class A {

public:

void show(char *msg)

{

printf("msg:%s/n", msg);

}

};

 

 

template<class T>

void* addressof(T t)

{

void *retValue;

__asm {

mov eax, t

mov retValue, eax

}

return retValue;

}

 

class DllModule;

 

class Function {

private:

void *addr;

int flags;

void *thisPtr;

union CalRet {

__int64 ll;

struct {

int lo;

int hi;

} i2;

char b8[8];

} ret;

public:

Function(void *func, int flag)

{

this->addr = func;

this->flags = flag;

this->thisPtr = NULL;

}

Function(HMODULE hmodule, const char *funcName, int flag)

{

this->addr = (void*)GetProcAddress(hmodule, funcName);

this->flags = flag;

this->thisPtr = NULL;

}

// Function(DllModule &dll, const char *funcName, int flag)

// {

//  this->addr = dll.get(funcName);

//  this->flags = flag;

//  this->thisPtr = NULL;

// }

Function(void *func, void *thisPtr, int flag)

{

this->addr = func;

this->thisPtr = thisPtr;

this->flags = flag;

}

int operator()(int nargs, ...)

{

callfn(addr, &nargs, nargs, thisPtr, flags, ret.b8);

return ret.i2.lo;

}

};

 

class DllModule {

private:

HMODULE hmodule;

char dllName[128];

public:

DllModule(const char *name)

{

hmodule = LoadLibrary(name);

strncpy(dllName, name, 127);

printf("load library %s/n", name);

}

~DllModule()

{

FreeLibrary(hmodule);

printf("free library %s/n", dllName);

}

void* get(const char *name)

{

return GetProcAddress(hmodule, name);

}

Function cFunc(const char *name, void *thisPtr = NULL)

{

return Function(get(name), thisPtr, DC_CDECL);

}

Function winFunc(const char *name, void *thisPtr = NULL)

{

return Function(get(name), thisPtr, DC_STADCALL);

}

};

 

int main(int argc, char* argv[])

{

int ret;

DllModule cdll("msvcrt.dll");

ret = cdll.cFunc("printf")(2, "Hello, %s/n", "baby");

printf("ret %d/n", ret);

DllModule user32("user32.dll");

ret = user32.winFunc("MessageBoxW")(4, 0, L"Hello", L"OK", 0);

printf("ret %d/n", ret);

ret = cdll.cFunc("strstr")(2, "Caller has already cleaned the stack", "has");

printf("ret %s/n", ret);

A a;

ret = Function(addressof(A::show), &a, DC_STADCALL)(1, "Class function call");

printf("ret %d/n", ret);

ret = user32.winFunc("FindWindowW")(2, NULL, L"Google - 谷歌浏覽器");

printf("ret %d/n", ret);

srand(cdll.cFunc("time")(1, NULL));

int r = rand();

ret = user32.winFunc("ShowWindow")(2, ret, (r % 2) == 0);

printf("r = %d, ret %d/n", r, ret);

return 0;

}

 摘自 lqefn的專欄
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved