找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 5380|回复: 1

vfp 中使用 BStr, SafeArray

[复制链接]

1214

主题

352

回帖

11

精华

管理员

菜鸟

积分
93755

贡献奖关注奖人气王精英奖乐于助人勋章

发表于 2011-7-17 20:54:26 | 显示全部楼层 |阅读模式
当我们调用其它语言编写的 DLL 或使用某些 COM / OCX 对象时,我们经常碰到要传递 BSTR 类型的字符串和 SafeArray 类型数组的问题。

BSTR  来自于 Basic 的字符串结构( Basic STRing),其结构是:[Length prefix] + [Data string] + [Terminator]
Length prefix  - 长度前缀, 4 字节, 不包含尾部结束标识的数据长度
Data string - 字符串数据, UniCode(Window)/Ansi(Mac) 格式, 中间可以包含 /0x00
Terminator - 结束标识, 两个 /0x00

要在 vfp 中构造这样的字符串有两种办法:
1. 利用 api 函数来构造,例如:
 m.cAnsiStr = 'ABCDEFG'
 m.cUnicodeStr = StrConv( m.cAnsiStr, 5 )

 Declare Long SysAllocString In Oleaut32 String sz
 m.pBStr = SysAllocString( m.cUnicodeStr+Chr(0)+Chr(0) )         && 指向 BSTR 的指针
 * ---------------------------------------------------------------------------------------
 * 这里我们可以看看 pBStr 指向地址的内容
 * ? StrConv( Sys( 2600, m.pBStr-4, 20 ), 15 )
 * 显示: 0E00000041004200430044004500460047000000
 * 其中
 *  长度前缀: 0E000000 - 14,也就是 cUnicodeStr  的长度
 *  字符数据: 4100420043004400450046004700 - cUnicodeStr 的内容
 *  结束符号: 0000
 * ---------------------------------------------------------------------------------------
 Declare Long SysFreeString In Oleaut32 String bstr
 SysFreeString( m.pBStr - 4 )                && 释放这个 BSTR

2. 自己构造,例如,用于 Window 平台的 BSTR:
 m.cAnsiStr = 'ABCDEFG'
 m.cUnicodeStr = StrConv( m.cAnsiStr + Chr(0), 5 )
 m.cBStr = BinToC( Len( m.cAnsiStr )*2, '4rs' ) + m.cUnicodeStr

实际应该用哪种要看被调用的函数声明方式,第二种方法传送的是指向完整结构的 BSTR 指针,因为 vfp 没有函数可以得到它自己的字符串地址指针,所以只能传送整个串的起始地址;但第一种方式传递的是指向 BSTR 中数据起始位置的指针,这也是为什么调用 SysFreeString 时要减去 4 的原因,不减去这个 4,SysFreeString 会返回串冲突错误(错误码 32)。

如果你同时熟悉 vfp 和 vb 的话,那么下面的代码:

m.cAnsiStr = 'ABCDEFG'
m.cUnicodeStr = StrConv( m.cAnsiStr + Chr(0), 5 )

m.cBStr = BinToC( Len( m.cAnsiStr )*2, '4rs' ) + m.cUnicodeStr
? Func1( m.cBStr )                       && 这里传送的相当于 vb 中 VarPtr( cBStr )

Declare Long SysAllocString In Oleaut32 String sz
m.pBStr = SysAllocString( m.cUnicodeStr )
? Func1( m.pBStr )                      && 这里传送的相当于 vb 中 StrPtr( cUnicodeStr )

===========================================================================

 

SafeArray 安全数组

SafeArray 的结构其实就是 vb 中数组结构,MS 的描述如下:
typedef struct tagSAFEARRAY {
   USHORT cDims;   // 这个数组有几维?
   USHORT fFeatures;  // 这个数组有什么特性?
   ULONG cbElements;  // 数组的每个元素有多大?
   ULONG cLocks;    // 这个数组被锁定过几次?
   PVOID pvData;    // 这个数组里的数据放在什么地方?
   SAFEARRAYBOUND rgsabound[ 1 ];
} SAFEARRAY

其中的 SAFEARRAYBOUND 定义如下:
typedef struct tagSAFEARRAYBOUND {
   unsigned long cElements;    // 这一维有多少个元素?
   long lLbound;     // 它的索引从几开始?
} SAFEARRAYBOUND

如果在 vb 中用 Dim MyArray ( 1 TO 8, 2 TO 10 ) As Long 来定义一个数组的话,实际的内存结构为:
  cDims = 2
fFeatures =
FADF_AUTO AND FADF_FIXEDSIZE
位置
0
cbElements = 4   LenB(Long) 4
cLocks = 0 8
pvData(指向真数组) 12
rgsabound(0).cElements = 8 16
rgsabound(0).lLbound = 1 18
rgsabound(1).cElements = 9 22
rgsabound(1).lLbound = 2 26

只有其中的“真数组”才存有真正的数组数据,它们与 C 中的数组结构是相同的。
同样的,Oleaut32 中也提供了创建/销毁/维护 SafeArray 的函数: SafeArrayCreate / SafeArrayDestroy / SafeArray...


【VB】QQ群:1422505加的请打上VB好友
【易语言】QQ群:9531809  或 177048
【FOXPRO】QQ群:6580324  或 33659603
【C/C++/VC】QQ群:3777552
【NiceBasic】QQ群:3703755

275

主题

3019

回帖

1

精华

管理员

嗷嗷叫的老马

积分
17066

论坛牛人贡献奖关注奖最佳版主进步奖人气王疯狂作品奖精英奖赞助论坛勋章乐于助人勋章

QQ
发表于 2011-7-22 14:33:51 | 显示全部楼层
SafeArray是个好东西
我就是嗷嗷叫的老马了......

您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表