首页
社区
课程
招聘
[原创]VC_VB的混合编译(二)实践进阶片
发表于: 2005-10-20 12:32 12316

[原创]VC_VB的混合编译(二)实践进阶片

2005-10-20 12:32
12316

在上一回我们已经实现VC,VB代码的混合编译,并成功的在VB代码中调用了VC代码中的一个无参数的函数,并取得了函数的返回值. 这一回我们将实践一下如何调用带参数的函数.
打开上一会的两个工程(LinkWithVC, vcobj). 切换到VB在form上添加一个按钮 name: cmdTestLong, 标题 TestLong. 在form上添加一个文本框txtInput 内容填 8. 再在ModVC中添加如下代码:
Public Function TestLong(ByVal lng As Long) As Long
TestLong = -1
End Function
在cmdTestLong的Click事件中添加代码 msgbox Testlong(clng(txtInput.Text))
现在我们来生成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::TestLong(void)" (?TestLong@ModVC@@AAGXXZ)
F:\LinkWithVC\LinkWithVC.exe : fatal error LNK1120: 1 unresolved externals
看到了吗,和第一次看到的错误Log除了函数名,完全是一样的……这时候想到了什么? 参数呢? 在VB代码中明明是有参数申明的啊? ….先不管它, 和上回一样在VC类中添加一个名为TestLong的同类型的空函数. 编译vc的obj,再生成VB的EXE,运行点击 TestLong按钮, 我们看到msgbox提示8, 和我们的参数8 一样!! 是巧合? 试试 改改 txtInput 中的数字. 再点击TestLong按钮. 我们会发现 msgbox提示的和txtInput文本框中的数字是一样的. 有了上回返回值的经验, 而我们的函数什么也没有做, 如是我们会知道 这个参数就 是存放在 eax中的(注:windows中fastcall的函数参数是采用寄存器传递的), 好了到了这里 我们知道怎么在VC代码中获取 vb代码传递的参数了. 可是在传递一个 long 型的数据 有什么实际用途呢?  一个 long 它就意味着 一个长整形数字、一个句柄、一个指针….我们来看一个实际的例子。
在Form上添加一个按钮cmdTestHwnd在按钮 TestHwnd的 Click事件中添加代码 call TestLong(txtInput.hWnd)
这里我们传递的是一个textbox的句柄。
我在VC函数中添加如下代码
void ModVC::TestLong()
{
    long hw;
    _asm mov hw,eax; //取得参数(TextBox的句柄)
    SetWindowText((HWND)hw,"VC: Hello VB");
   
}
重复操作,生成我们的EXE,。。。我们会发现失败了,打开log看看。
Microsoft (R) Incremental Linker Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

ModVC.OBJ : error LNK2001: unresolved external symbol __imp__SetWindowTextA@8
F:\LinkWithVC\LinkWithVC.exe : fatal error LNK1120: 1 unresolved externals
熟悉VC的一看就知道连接的时候没有把User32.lib连接进去。
解决方法有两个1个是在VC代码中使用LoadLibray,GetProcessAddress的方式调用这个api,另一个方法就是 让连接器 把user32.Lib连接进去。 显然如果要大量使用api函数的话第一中方法太繁琐。我们用第二个方法。怎么做了呢?还记得上一回的 自定义连接配置文件吗。
[Settings]
lib=1
log=1

[OBJ]
F:\LinkWithVC\vcobj\Release\ModVC.obj=F:\LinkWithVC\ModVC.obj

[lib]
1=User32.lib
Settings段的lib 表示 [lib]段中的lib数目。 在lib段 我按照顺序1=…,2=… 添加我们要连接的lib即可,当然也可以是obj文件。
好我们再来操作,生成EXE,OK。运行点击TestHwnd。好了我们看到TextBox中的文字变成了 VC: Hello VB 。
我们再来试试字符串。
在form上添加一个按钮TestString 在ModVC中添加函数
Public Function TestString(ByVal s As String) As Long
Rem nothing
End Function
TestString的Click事件中添加如下代码
Private Sub CmdTestString_Click()
Dim s As String
s = Space(256) '为s分配空间
Call TestString(s)
MsgBox s
End Sub
在VC中添加同名函数
void ModVC::TestString()
{
    char* p;
    _asm mov p,eax; //取得参数(TextBox的句柄)
    memset(p,0,256);//我们知道字符串的长度是256
    lstrcpy(p,"VC: Hello VB");
   
}
编译,生成EXE,运行,点击TestString按钮,。。。咦,显示的是乱码!!??这是因为VB中的String用的是Unicode,VC中复制的不是。转一下就可以了。就在vb中转吧vb有一个函数很方便。把msgbox s 改为 MsgBox StrConv(s, vbUnicode),再生成EXE运行,这次OK了。
接下来我们再试试传递结构体。函数参数格式的声明我们可以参考一下VB中API函数的声明。我来个简单点的结构体 POINTAPI, 用VB的 API Viewer 找到
Public Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long

Public Type POINTAPI
        x As Long
        y As Long
End Type
参照这个我们在ModVC中添加函数
Public Function TestStruct(lppt As POINTAPI) As Long
Rem
End Function
在form上添加一个按钮TestStruct,在Click中添加代码
Private Sub cmdTestStruct_Click()
Dim pt As POINTAPI
Call TestStruct(pt)
MsgBox "x= " & pt.x & " y=" & pt.y
End Sub
在VC类中添加同名同类型函数。
void ModVC::TestStruct()
{
    POINT *pt;
    _asm mov pt,eax;//获取 指针参数
    pt->x = 123;
    pt->y = 456;
}
编译运行。。。。我们会发现 非法操作。大概是说引用了0x00000000处的内存。看这个内存地址我们会知道 在vc中引用了一个空指针,那就是说eax的值是0。那则么回事参数没有在eax里面,参数跑哪里去了?在其它寄存器?不太可能。。。那会在哪里呢,我们总不能凭空变出来一个参数吧。想想C++类中有什么可以用的符号?嗯,有一个 this 指针。会是它吗,熟悉VC的人应该知道在调用类成员函数时会先将该类的this指针存放到 eax 中。看来他们有很大的关系。那就动手试试。函数改为如下:
void ModVC::TestStruct()
{
    POINT *pt=(POINT)this;
    pt->x = 123;
    pt->y = 456;
}
再编译,生成EXE运行。OK!成功了,看到了 x= 123 y=456 .
我们再回过头来看看前面的函数 ,都假设把this 当着参数试试,经过测试假设成立。如是我们知道this 就是传递过来的参数,当参数是long是,同时eax中也有这个参数值的一个副本。
到现在看来似乎是大功告成了,还没有!还有一个难题,this就只有一个,如果要传递2个,3个,4个。。。参数怎么办呢?

程序代码下载


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (4)
雪    币: 1334
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
赫赫 “猪肉罐头”混合“牛肉罐头”
2005-10-20 15:51
0
雪    币: 313
活跃值: (250)
能力值: ( LV9,RANK:650 )
在线值:
发帖
回帖
粉丝
3
非常强支持,先学习一下分析。
2005-10-20 18:01
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
好强悍哟
看来我也得学习学习了哈!!!
2005-10-23 15:30
0
雪    币: 30
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
非常支持,先学习一下分析。
2015-10-28 17:34
0
游客
登录 | 注册 方可回帖
返回
//