首页
论坛
课程
招聘
[原创]VC VB 的混合编译(三)多参数篇
2005-10-20 18:53 11397

[原创]VC VB 的混合编译(三)多参数篇

2005-10-20 18:53
11397
在上一回我们已经实现VB调用VC函数并传递一个long、窗口句柄、字符串指针、结构体指针的参数,并取得了函数的返回值。 这一回我们将实践一下如何传递多个参数。
打开上一回的两个工程(LinkWithVC, vcobj). 切换到VB在form上添加一个按钮 name: cmdTestStruct2, 标题 Test Struct 2。再在ModVC中添加如下代码
Public Function TestArg(lppt1 As POINTAPI, lppt2 As POINTAPI) As Long
Rem
End Function
在cmdTestStruct2的Click事件中
Private Sub cmdTestStruct2_Click()
Dim pt1 As POINTAPI, pt2 As POINTAPI
Call TestArg(pt1, pt2)
MsgBox "x= " & pt1.x & " y=" & pt1.y & vbCrLf & "x= " & pt2.x & " y=" & pt2.y
End Sub
好,现在生成EXE,必然不成功。我们打开log看会是什么错误信息,
Microsoft (R) Incremental Linker Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

Form1.OBJ : error LNK2001: unresolved external symbol "private: void __stdcall ModVC::TestArg(void)" (?TestArg@ModVC@@AAGXXZ)
F:\LinkWithVC\LinkWithVC.exe : fatal error LNK1120: 1 unresolved externals
我们看到连接器要求的函数声明和 无参数,1 个参数的相同,经过测试不能在VB模块声明的函数有多少个参数编译后都是 private: void __stdcall FunctionName(void ) 。
好了我们熟练的在VC的类中加上对应的TestArg函数。编译,生成EXE,通过。
下面来解决我们的难题,现在我们从VC程序的角度来说 函数声明是一样的参数个数却是不确定的。这时我们应该会想到C 函数中有一种可变参数的函数,这种函数要求至少有一个确定参数,然后使用一组宏获取其它参数。这里我们先复习一下 C语言中可变参数的用法
http://redcheek.net/blogview.asp?logID=67
复习完了我们知道函数该怎么写了,如下:
void ModVC::TestArg()
{   
    LPPOINT lppt1,lppt2;
    va_list ap;
    lppt1 = (LPPOINT)this;
    va_start(ap,this);
    lppt2 = va_arg(ap,LPPOINT);
    lppt1->x = 123;
    lppt1->y = 456;
    lppt2->x = 321;
    lppt2->y = 654;
}
这样子,能行吗,编译试试;
-------------------Configuration: vcobj - Win32 Release--------------------
Compiling...
ModVC.cpp
F:\LinkWithVC\vcobj\ModVC.cpp(72) : error C2102: '&' requires l-value
Error executing cl.exe.

ModVC.obj - 1 error(s), 0 warning(s)
显然编译失败了。
This 是一个 r-value,无法取地址。现在我们知道只要取得了this的地址我们的问题就解决了。那怎么知道this的地址呢。。。不知道大家有什么好方法没有,老实说,我没有,如果谁有更好的方法别忘了告诉我一声哦。
不过我有一个很笨的方法:跟踪调试程序在内存中找答案。
为了便于调试我更改函数内容为如下:
void ModVC::TestArg()
{
    char p[256];
    lstrcpy(p,"break here!");
    _asm mov eax,1;
    _asm mov eax,2;
    _asm mov eax,3;
    _asm mov eax,this;
    _asm mov eax,4;
    _asm mov eax,5;
    _asm mov eax,6;
}
编译,生成EXE。我们现在使用ollydbg来调试 LinkWithVC.exe,打开这个程序,使用od的搜功能,搜索参考字符串,然后在 break here! 哪里设置一个断点。运行程序,点按钮,程序会在下面红色的地方中断。
004012C0  /$ 55             PUSH EBP
004012C1  |. 8BEC           MOV EBP,ESP
004012C3  |. 81EC 00010000  SUB ESP,100
004012C9  |. 8D85 00FFFFFF  LEA EAX,DWORD PTR SS:[EBP-100]
004012CF  |. 68 30604000    PUSH LinkWith.00406030   ; /String2 = "break here!"
004012D4  |. 50             PUSH EAX               ; |String1 = 0012F300
004012D5  |. FF15 C0104000  CALL DWORD PTR DS:[<&KERNEL32.lstrcpyA>] ; \lstrcpyA
004012DB  |. B8 01000000    MOV EAX,1
004012E0  |. B8 02000000    MOV EAX,2
004012E5  |. B8 03000000    MOV EAX,3
004012EA  |. 8B45 08        MOV EAX,DWORD PTR SS:[EBP+8]
004012ED  |. B8 04000000    MOV EAX,4
004012F2  |. B8 05000000    MOV EAX,5
004012F7  |. B8 06000000    MOV EAX,6
004012FC  |. 8BE5           MOV ESP,EBP
004012FE  |. 5D             POP EBP
004012FF  \. C2 0400        RETN 4
看看上面蓝色的代码,如是我们知道那条绿色的代码对应的源程序就是 mov eax, this;
如是 我们知道了this的地址就是 [ebp+8].

程序代码下载

2022 KCTF春季赛【最佳人气奖】火热评选中!快来投票吧~

收藏
点赞0
打赏
分享
最新回复 (5)
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
心已欠费 活跃值 2005-10-23 13:08
2
0
这个看起来又点复杂哦
雪    币: 1613
活跃值: 活跃值 (33)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
北极星2003 活跃值 25 2005-10-24 17:21
3
0
三片创意之作,好!!
好久没来,又出高人了
有时间定要好好学习
雪    币: 564
活跃值: 活跃值 (23)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lixupeng 活跃值 2009-4-2 10:51
4
0
精彩啊!!!!!
雪    币: 91
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
boylk 活跃值 2009-4-22 00:52
5
0
问下,这种混合编译有何实际的意义呢?
雪    币: 203
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xieyulin 活跃值 2010-6-3 15:59
6
0
这种方法不实用,有没有其他更好的方法,dll,com方式除外。
游客
登录 | 注册 方可回帖
返回