刚才试了如下情况,是可以复制的 Private Type tagMy szttt As String nnn As Long End TypeDim ddf As tagMy Dim ddf2 As tagMy ddf2.szttt = "hhhh" CopyMemory ddf, ddf2, LenB(ddf) ddf2.szttt = "fffaaaaa"难道是com导出的结构体有问题??
你用oleview看看结构体是怎么定义的,我怀疑是你结构体定义的问题
这是人家给的demo工程里的结构体定义,真正的com还没给我,只是让先研究一下如何使用 typedef enum { cloudy = 0, sunny = 23 } CloudCover;typedef struct tagCOMPONENT_INFO2 { BSTR bstrName; CloudCover eCover; long bOK; long l; short s; } COMPONENT_INFO2;typedef struct tagCOMPONENT_INFO3 { COMPONENT_INFO2 info2; CloudCover eCover; long bOK; } COMPONENT_INFO3;
呵呵,习惯在调用API时,与LPSTR打交道,碰到BSTR真是亲切!它就是VB自己支持的自动化类型。但放在结构中,还真不敢确定怎么用它。 为自动化类型写的Dll,按MSDN中的说法,是可以直接Byref引用的,也就是说按原结构声明一个相同类型的结构,直接交给DLL就行了。若不行,可试试以下方案: BSTR是以指针传递的,所以string在结构中就是一个Long指针,指向一个BSTR字符串 你的结构应声明成Long, Private Type tagMy szttt As long nnn As Long End Type 先copymemory出这个结构,然后,再从结构中copymemory出你的String。 因是BSTR,所以copy这个String时不要用Byval String,而用下面形式: dim s1 as string,s as string copymemory byval varptr(s),byref tagMy.szttt,4'先用VB的String仿冒这个BSTR s1=s'用VB的方法复制取回BSTR copymemory byval varptr(s),byref 0&,4'要还原s的指针,不然VB可能会崩的 s1是数据上面方法不一定可行,因是BSTR,在使用API时反而让VB有些难了。也许直接用VB取得,才是正路。
Private Type tagMy
szttt As String
nnn As Long
End TypeDim ddf As tagMy
Dim ddf2 As tagMy
ddf2.szttt = "hhhh"
CopyMemory ddf, ddf2, LenB(ddf)
ddf2.szttt = "fffaaaaa"难道是com导出的结构体有问题??
typedef enum {
cloudy = 0,
sunny = 23
} CloudCover;typedef struct tagCOMPONENT_INFO2 {
BSTR bstrName;
CloudCover eCover;
long bOK;
long l;
short s;
} COMPONENT_INFO2;typedef struct tagCOMPONENT_INFO3 {
COMPONENT_INFO2 info2;
CloudCover eCover;
long bOK;
} COMPONENT_INFO3;
为自动化类型写的Dll,按MSDN中的说法,是可以直接Byref引用的,也就是说按原结构声明一个相同类型的结构,直接交给DLL就行了。若不行,可试试以下方案:
BSTR是以指针传递的,所以string在结构中就是一个Long指针,指向一个BSTR字符串
你的结构应声明成Long,
Private Type tagMy
szttt As long
nnn As Long
End Type
先copymemory出这个结构,然后,再从结构中copymemory出你的String。
因是BSTR,所以copy这个String时不要用Byval String,而用下面形式:
dim s1 as string,s as string
copymemory byval varptr(s),byref tagMy.szttt,4'先用VB的String仿冒这个BSTR
s1=s'用VB的方法复制取回BSTR
copymemory byval varptr(s),byref 0&,4'要还原s的指针,不然VB可能会崩的
s1是数据上面方法不一定可行,因是BSTR,在使用API时反而让VB有些难了。也许直接用VB取得,才是正路。
但不知为什么只能一个一个的copy,一次拷贝数量>1时还是崩溃
但是这个方法很笨,据说那个com中导出了n个struct,不能都重新定义一遍啊!!到底问题出在哪里?
若是ANSI,可能是某次调用API采用了Byval传递String,这样调用VB用自动将Unicode转成ANSI。
一次拷贝数量>1时还是崩溃
=======================崩溃的原因,我能想到的有两种:
1、是结构长度不对,这一点,通过验证结构第一与最后一个元素的值是否正确,即可轻易查出;
2、就是出在String类型上,BSTR是以指针传递,用copymemory或非VB方式复制String或含有String的结构,都是不可靠且暂时的,因为VB不知道这些变化,当这些String需重置时(如:重新赋值),VB会自动释放旧数据内存,因为这部分内存非VB申请所得,所以常会出错。
可靠一点的办法是,用VB赋值方法将Copy取得的String或结构再赋值给一个新的VB变量,然后同样用Copy方法恢复原String或结构的指针。这一点,前面回贴中已写了相关示例。
--------------------------
结构体的size没问题,我已经考虑了内存对齐.
由于问题出在一次拷贝数量>1时(即数组的复制时),所以我怀疑vb数组的相邻两个元素之间有段空白内存,但这个只是怀疑2、String问题
---------------------------
这个方法感觉很复杂,如果结构体中string比较多,实现代价会很大. 但还是谢谢
homezj(小吉)的方法应该是可行的,就是先copy这个BSTR,然后再copy指针。或者考虑不用结构,直接定义一个byte()来传递参数,只是COM传的数组要知道大小,然后再拆开