实时编译、动态执⾏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小时内删除。
发表评论