实时编译、动态执⾏CC++源码函数实时编译、动态执⾏C/C++源码函数
语法格式:fileCLASS *pObj = <file.cpp>
该语法获得源代码file.cpp的函数接⼝对象指针pObj,通过pObj调⽤file.cpp的
函数。
参数: file.cpp: c/c++源代码⽂件名。
返回值:fileCLASS *pObj: 接⼝对象地址。
1. 编写c/c++源码函数接⼝
struct rootCLASS    //函数对象名字
{
virtual char* _stdcall getstr(char *aptr);                  //定义函数0
virtual void _stdcall getval(double aval,char *aptr);        //定义函数1
virtual double _stdcall sqrt(int aval);                      //定义函数2
};
头⽂件: root.h (定义了3个接⼝函数)
#include "root.h"          //定义对象的头⽂件
char* rootCLASS::getstr(char *aptr)    //实现函数0
{
printf("江南好\n%s",aptr);
404页面网站源码
return `⽇出江花红似⽕, `;
}
void rootCLASS::getval(double aval,char *aptr)          //实现函数1
{
double dd = aval + 0.00002227;
printf(`春来江⽔绿如蓝 -- "%0.8f"\n%s\n`,dd,aptr);
}
double rootCLASS::sqrt(int aval)    //实现函数2
{
return ::sqrt(aval);
}
rootCLASS ROOT;          //声明接⼝变量
void* main(void **pObj)
{
*pObj = &ROOT;    //把接⼝地址传给⽤户
return []()      //返回Lambda函数⽤于资源清理
{
printf("Exit.\n");
};
}
c/c++⽂件: root.cpp (实现源码函数接⼝)
2.编写程序调⽤root.cpp的函数
#include "root.h"    //定义ROOT对象的头⽂件
void main()
{
rootCLASS *ROOT = <root.cpp>;        //该语句取出root.cpp的函数对象地址
if(!ROOT) return;                    //若root.cpp有语法错误,则ROOT=null
printf("%s\n",ROOT->getstr("风景旧曾谙\n"));  //调⽤root.cpp的getstr函数
ROOT->getval(2014.0720,"能不忆江南");          //调⽤root.cpp的getval函数
printf("%f\n",ROOT->sqrt(3));                  //调⽤root.cpp的sqrt函数
}
c/c++⽂件: like.cpp (调⽤root.cpp函数)
编译执⾏:
⽤YC命令: ycc like.cpp ⽣成 。执⾏后,输出下列⽂字:
江南好
风景旧曾谙
⽇出江花红似⽕,
春来江⽔绿如蓝 – “2014.07202227”
能不忆江南
1.732051
Exit.
分析:
1. ⽂件root.cpp和root.h⼀起为应⽤程序提供⼀个函数接⼝:rootCLASS ROOT。
2. 语句rootCLASS *ROOT = <root.cpp>将源代码root.cpp编译转换为执⾏代码⽂件:
www \…p
之后执⾏代码被调⼊内存,like.cpp变量rootCLASS ROOT的地址被传给root.cpp的主函数:void main(void **pObj){},主函数通过语句 *pObj = &ROOT 把root.cpp的函数接⼝对象地址&ROOT传给like.cpp的rootCLASS *ROOT。
like.cpp通过语句下列语句:
ROOT->getstr()
ROOT->getval()
ROOT->sqrt()
调⽤root.cpp的接⼝函数。
3. 程序退出时,⾃动检查root.cpp主函数main()是否有函数指针返回,若有,则执⾏它,以便释放root.cpp可能申请的系统资源。本例
root.cpp主函数的返回值为lambda函数:{ printf(“Exit.\n”); };
4. 将root.cpp调⼊YC编辑器后,按Ctrl+F5键,⽣成下列汇编代码,分析汇编代码可更好
地理解接⼝源码。
#include  "root.cpp"              2020-01-11  12:40:30    0
#include  "include/ycapi.h"        2020-01-10  14:39:02    1
#include  "root.h"                2020-01-10  17:38:26    2
0    printf
1    sqrt
void entry()
{
00000000 6800000000  push  0x00000000
00000005 e802000000  call  void *main(void **pObj) (0000000C=000000A+0000002)//root.cpp 21
0000000A 59          pop    ecx
0000000B c3          ret
}
root.cpp 20  arglen=4
void *main(void **pObj)
{
0000000C 8b442404      mov  eax,dword [esp+04h]
00000010 c700d8000000  mov  dword [eax],0x000000D8  //struct rootCLASS ROOT (root.cpp 19)
00000016 b884000000    mov  eax,0x00000084    //global=00000017  返回函数的地址
0000001B c3            ret
}
root.h 3  arglen=8
root.cpp 3
virtual char *stdcall rootCLASS::getstr(char *aptr)
{
0000001C 55            push    ebp
0000001C 55            push    ebp
0000001D 8bec          mov    ebp,esp
0000001F 51            push    ecx
00000020 ff750c        push    dword [ebp+0Ch]        //aptr  (root.cpp 2)
00000023 6890000000    push    0x00000090        //"江南好\n%s"  (root.cpp 4) 00000028 e87fdbff8e    call    int printf(const char *_Format, ...) //include/stdio.h 264 0000002D 83c408        add    esp,0x00000008
00000030 b89c000000    mov    eax,0x0000009C        //"⽇出江花红似⽕, "  (root.cpp 5) 00000035 8be5          mov    esp,ebp
00000037 5d            pop    ebp
00000038 c20800        ret    0008
}
root.h 4  arglen=10
root.cpp 9
virtual void stdcall rootCLASS::getval(double aval,char *aptr)
{
0000003B 55            push    ebp
0000003C 8bec          mov    ebp,esp
0000003E 83ec0c        sub    esp,0x0000000C
00000041 dd450c        fld    qword [ebp+0Ch]        //aval  (root.cpp 8)
00000044 dc05e8000000  fadd    qword [000000E8]      //zeroName  (include/yca.h 0) 0000004A dd5df8        fstp    qword [ebp-08h]        //dd  (root.cpp 10)
0000004D ff7514        push    dword [ebp+14h]        //aptr  (root.cpp 8)
00000050 ff75fc        push    dword [ebp-04h]        //dd+4 (00064c99 + 4)  (root.cpp 10) 00000053 ff75f8        push    dword [ebp-08h]        //dd  (root.cpp 10)
00000056 68b0000000    push    0x000000B0            //"春来江⽔绿如蓝 -- \"%0.8f\"\n%s\n" 0000005B e87fdbff8e    call    int printf(const char *_Format, ...) (8EFFDB7F)//stdio.h 264 00000060 83c410        add    esp,0x00000010
00000063 8be5          mov    esp,ebp
00000065 5d            pop    ebp
00000066 c21000        ret    0010
}
root.h 5  arglen=8
root.cpp 15
virtual double stdcall rootCLASS::sqrt(int aval)
{
00000069 55            push        ebp
0000006A 8bec          mov        ebp,esp
0000006C 51            push        ecx
0000006D db450c        fild        dword [ebp+0Ch]        //aval  (root.cpp 14)
00000070 83ec08        sub        esp,0x00000008
00000073 dd1c24        fstp        qword [esp]
00000076 e820dbff8e    call        double sqrt(double _X) (8EFFDB20) //include/math.h 521 0000007B 83c408        add        esp,0x00000008
0000007E 8be5          mov        esp,ebp
00000080 5d            pop        ebp
00000081 c20800        ret        0008
}
root.cpp 23  arglen=0
void stdcall lamb_0000032()    //Lambda函数虽在局部定义,却在全局实现
{
00000084 68d0000000    push      0x000000D0        //"Exit.\n"  (root.cpp 25)
00000089 e87fdbff8e    call      int printf(const char *_Format, ...) //include/stdio.h 264 0000008E 59            pop      ecx
0000008F c3            ret
}
// strings 代码中所⽤到的字符串
00000090        db    12    "江南好\n%s"                        //root.cpp 4
0000009C        db    20    "⽇出江花红似⽕, "                  //root.cpp 5
000000B0        db    32    "春来江⽔绿如蓝 -- \"%0.8f\"\n%s\n"  //root.cpp 11
000000D0        db    8    "Exit.\n"                            //root.cpp 25
// variables ⽤户声明或编译器⾃动⽣成的全局变量 ///
000000D8        struct rootCLASS ROOT                                          dd  000000DC
000000DC        virtual char *stdcall rootCLASS::getstr(char *aptr)            dd  0000001C
000000E0        virtual void stdcall rootCLASS::getval(double aval,char *aptr)  dd  0000003B
000000E4        virtual double stdcall rootCLASS::sqrt(int aval)                dd  00000069
000000E8        zeroName                                                dq  3EF75A0EBF358A7B
000000F0 The End  -  240 bytes
// stack = 1 * 1048576 bytes
5. 看看下⾯like.cpp的汇编代码(在YC编辑器的⼯具菜单中⽣成),有助于理解该语法的实
现过程。
#include  "like.cpp"                      2020-01-11  09:30:08    0
#include  "include/ycapi.h"                2020-01-10  14:39:02    1
#include  "root.h"                        2020-01-10  17:38:26    2
0    YC_ExpFree
1    YC_ExpLoad
2    printf
like.cpp 2  arglen=0
void main()
{
00000000 53              push  ebx        //ebx=ROOT  (like.cpp 4)
00000001 68a0000000      push  0x000000A0        //zeroName  (include/yca.h 0)
00000006 68a4000000      push  0x000000A4        //zeroName  (include/yca.h 0)
0000000B 68a8000000      push  0x000000A8        //zeroName  (include/yca.h 0)
00000010 e8f2d8ff8e      call  void stdcall YC_ExpLoad(void *pSrc,void *pHandle,void *pObj) 00000015 8b1da0000000    mov    ebx,dword [000000A0] //zeroName  (include/yca.h 0)
0000001B 85db            test  ebx,ebx
0000001D 744e            je    0000006D = 0000001F+0000004e
0000001F 6884000000      push  0x00000084        //"风景旧曾谙\n"  (like.cpp 6)
00000024 8bcb            mov    ecx,ebx
00000026 51              push  ecx
00000027 8b01            mov    eax,dword [ecx]
00000029 ff10            call  dword [eax]      //调⽤ROOT->getstr()
0000002B 50              push  eax
0000002C 6880000000      push  0x00000080        //"%s\n"  (like.cpp 6)
00000031 e87fdbff8e      call  int printf(const char *_Format, ...) //include/stdio.h 264
00000036 83c408          add    esp,0x00000008
00000039 6890000000      push  0x00000090        //"能不忆江南"  (like.cpp 7)
0000003E 6849789f40      push  0x409F7849
00000043 683f355eba      push  0xBA5E353F
00000048 8bcb            mov    ecx,ebx
0000004A 51              push  ecx
0000004B 8b01            mov    eax,dword [ecx]
0000004D ff5004          call  dword [eax+04h]    //调⽤ROOT->getval()
00000050 6a03            push  0x00000003
00000052 8bcb            mov    ecx,ebx
00000054 51              push  ecx
00000055 8b01            mov    eax,dword [ecx]
00000057 ff5008          call  dword [eax+08h]    //调⽤ROOT->sqrt()
0000005A 83ec08          sub    esp,0x00000008
0000005D dd1c24          fstp  qword [esp]
00000060 689c000000      push  0x0000009C        //"%f\n"  (like.cpp 8)
00000065 e87fdbff8e      call  int printf(const char *_Format, ...) //include/stdio.h 264
0000006A 83c40c          add    esp,0x0000000C
0000006D 5b              pop    ebx
0000006E c3              ret
}
void yc_end()  //由编译器根据是否有需要释放的资源⽽⾃动⽣成的函数,程序退出时⾃动执⾏
{
0000006F 68a4000000  push  0x000000A4        //zeroName  (include/yca.h 0)
00000074 68a8000000  push  0x000000A8        //zeroName  (include/yca.h 0) 00000079 e8f3d8ff8e  call  void stdcall YC_ExpFree(void *pSrc,void *pHandle) //yca.h 133 0000007E c3          ret
}
// strings 代码中所⽤到的字符串
00000080        db    4    "%s\n"                      //like.cpp 6
00000084        db    12    "风景旧曾谙\n"              //like.cpp 6
00000090        db    12    "能不忆江南"                //like.cpp 7
0000009C        db    4    "%f\n"                      //like.cpp 8
// variables⽤户声明或编译器⾃动⽣成的全局变量 //
000000A0        zeroName        dd  00000000    //ldpos=000000A0      include/yca.h 0 000000A4        zeroName        dd  00000000    //include/yca.h 0
000000A8        zeroName        dd  00000000    //include/yca.h 0
000000AC The End  -  172 bytes
语法细节:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。