从C++ DLL中获取结构数组问题.
C++的DLL部分定义如下:typedef char DBITBLNAME [261];
typedef char DBINAME [32];
#ifndef UINT16
#if defined(__FLAT__)
# define UINT16 unsigned short
#else
# define UINT16 unsigned int
#endif // defined(__FLAT__)
#endif // UINT16
#ifndef INT16
#if defined(__FLAT__)
# define INT16 short
#else
# define INT16 int
#endif // defined(__FLAT__)
#endif // INT16
typedef struct {
DBITBLNAME szName;
UINT16 iFNameSize;
DBINAME szTableType;
UINT16 iFields;
UINT16 iRecSize;
UINT16 iRecBufSize;
UINT16 iKeySize;
UINT16 iIndexes;
UINT16 iValChecks;
UINT16 iRefIntChecks;
UINT16 iBookMarkSize;
short bBookMarkStable;
DBIOpenMode eOpenMode;
DBIShareMode eShareMode;
short bIndexed;
INT16 iSeqNums;
short bSoftDeletes;
short bDeletedOn;
UINT16 iRefRange;
XLTMode exltMode;
UINT16 iRestrVersion;
short bUniDirectional;
PRVType eprvRights;
UINT16 iFmlRights;
UINT16 iPasswords;
UINT16 iCodePage;
short bProtected;
UINT16 iTblLevel;
DBINAME szLangDriver;
short bFieldMap;
UINT16 iBlockSize;
short bStrictRefInt;
UINT16 iFilters ;
short bTempTable ;
UINT16 iUnUsed[16];
} CURProps;
typedef CURProps far *pCURProps;
DBIResult DBIFN DbiGetCursorProps (
hDBICur hCursor,
pCURProps pcurProps
);
VB调用部分代码如下:
Public Type CURProps
szName(1 To 261) As Byte
iFNameSize As Integer
szTableType(1 To 32) As Byte
iFields As Integer
iRecSize As Integer
iRecBufSize As Integer
iKeySize As Integer
iIndexes As Integer
iValChecks As Integer
iRefIntChecks As Integer
iBookMarkSize As Integer
bBookMarkStable As Integer
eOpenMode As DBIOpenMode
eShareMode As DBIShareMode
bIndexed As Integer
iSeqNums As Integer
bSoftDeletes As Integer
bDeletedOn As Integer
iRefRange As Integer
exltMode As XLTMode
iRestrVersion As Integer
bUniDirectional As Integer
eprvRights As PRVType
iFmlRights As Integer
iPasswords As Integer
iCodePage As Integer
bProtected As Integer
iTblLevel As Integer
szLangDriver(1 To 32) As Byte
bFieldMap As Integer
iBlockSize As Integer
bStrictRefInt As Integer
iFilters As Integer
bTempTable As Integer
iUnUsed(1 To 16) As Integer
End Type
Public Declare Function DbiGetCursorProps Lib "IDAPI32.dll" (ByVal hcursor As Long, pcurProps As CURProps) As Integer
运行后发现. CURProps结构中, 数据不对. iFields应该是Field Count, 明明表中只有10个Field, 但得到的数据却是32256. 结构中其他field数据也都不正常, 怀疑是VB对此结构体的定义与C++中的没有对齐, 但实在是找不出哪儿有问题. 请高手赐教! 急等. 多谢了. --------------------编程问答-------------------- szName(1 To 261) As Byte 改为262试试看 后面会有1字节填充的. --------------------编程问答-------------------- to akirya:
感谢你的回复, 这样也是得不到正确结果的. --------------------编程问答-------------------- 你先检查下字节对齐了吗?你还有几个结构没贴出来 --------------------编程问答-------------------- 先把所用的结构都贴全了,然后传递一个看看,看看在那几个变量是不正确的. --------------------编程问答-------------------- .......好象没啥好说的了.... --------------------编程问答-------------------- C中的DBIOpenMode、DBIShareMode等如何定义?
在C中取得sizeof(CURProps),与VB中的Len(pcurProps)比较是否一致? --------------------编程问答-------------------- sorry, 我忘记说了, DBIOpenMode、DBIShareMode等没贴出来的都是enum.
C++部分
typedef enum
{
dbiREADWRITE = 0,
dbiREADONLY = 1
} DBIOpenMode;
typedef enum
{
dbiOPENSHARED = 0,
dbiOPENEXCL = 1,
} DBIShareMode;
typedef enum
{
xltNONE = 0,
xltRECORD = 1,
xltFIELD = 2,
} XLTMode;
typedef enum {
prvNONE = 0,
prvREADONLY = 0x01,
prvMODIFY = 0x03,
prvINSERT = 0x07,
prvINSDEL = 0x0F,
prvFULL = 0x1F,
prvUNKNOWN = 0xFF
} PRVType;
VB部分:
Public Enum DBIOpenMode
dbiREADWRITE = 0
dbiREADONLY = 1
End Enum
Public Enum DBIShareMode
dbiOPENSHARED = 0
dbiOPENEXCL = 1
End Enum
Public Enum XLTMode
xltNONE = 0
xltRECORD = 1
xltFIELD = 2
End Enum
Public Enum PRVType
prvNONE = 0
prvREADONLY = &H1
prvMODIFY = &H3
prvINSERT = &H7
prvINSDEL = &HF
prvFULL = &H1F
prvUNKNOWN = &HFF
End Enum
To Chenghui530:
目前的确是怀疑未对齐, 但一时半会没找出是哪儿出了问题...
To Tiger_Zhao:
对于C/C++, 只能看看源码...
To All:
请各位多帮忙. 感谢. --------------------编程问答-------------------- len(结构)是否等于sizeof(结构) --------------------编程问答-------------------- to chenhui530:
现在无法去试. 晚点试过再请教了. 谢谢了. --------------------编程问答-------------------- 注意:VB中的Enum是Long(Int32)!
你C中的enum是多少? --------------------编程问答-------------------- 注意这句:#ifndef UINT16
这里的意思是说:如果定义了UINT16
你看看*.h文件中有没有定义这个类型
C中int类型等于VB的Long类型
如果有的话,则变量类型为Integer,如果没有则为Long
如果枚举的话,VB只支持Long类型,所以一般是没什么问题的
--------------------编程问答-------------------- >如果枚举的话,VB只支持Long类型,所以一般是没什么问题的
好像记得C中enum的字节数可以配置的,所以不能保证。 --------------------编程问答-------------------- 怎么不做个COM接口 --------------------编程问答-------------------- 来罐下水! --------------------编程问答-------------------- --------------------编程问答-------------------- 首先感谢大家的回复. 这个API实际上是Borland BDE Engine里的一个API, 我没有源码:). 也不可能拿到有COM接口的DLL. :p 由于手上目前没有VC++, 所以还真的试不出sizeof(CURProps)所占内存的大小, 真是头痛啊...引出这个问题的原因是, 我需要修改从第三方处获得的paradox文件的column name. 不得已需要直接调用这些API. --------------------编程问答-------------------- to Sandrer:
UINT16的定义我在最开始已经贴出来了.
#ifndef UINT16
#if defined(__FLAT__)
# define UINT16 unsigned short
#else
# define UINT16 unsigned int
#endif // defined(__FLAT__)
#endif // UINT16
因为不太理解__FLAT__的含义, 所以只是译成了integer. 之后也有尝试过long, 但采用long会报错. --------------------编程问答-------------------- 刚刚找来个Visual Studio.Net中的VC++.Net试了一下, len(CURProps)和sizeof(CURProps)都是427. 我晕了. 哪位老大来救救命... --------------------编程问答-------------------- 友情顶一下 --------------------编程问答-------------------- --------------------编程问答-------------------- 没人解答了嘛? 很奇怪, C++和VB中定义的2个结构长度一样, C++里的enum我看过也是4个字节的. 真的是搞不懂了... --------------------编程问答-------------------- 你的DLL是用哪个编译器编的就在该编译器上进行测试,不同的C编译器有差异的。 --------------------编程问答-------------------- To Tiger_Zhao:
这个dll是borland提供的, 事实上我也不知道是哪个编译器编译的. 我从codeproject上找到一个vc写的call这个DLL部分API的demo, 是可以正常获得数据的...之前的sizeof(CURProps)等于427也是在这个demo的环境中得到的. --------------------编程问答-------------------- 应该就是对齐的问题,如下
Sub Main()
Dim t As CURProps, a(2 - 1) As CURProps
Debug.Print Len(t), VarPtr(a(1)) - VarPtr(a(0))
End Sub
输出为:
427 432
你只能用一个够大的Byte数组调用函数,然后用CopyMemory的方式逐个复制到结构中。 --------------------编程问答-------------------- To Tiger_Zhao:
之前我是直接传一个结构地址给API的, 后来也试过声明一个427个元素的byte array, 然后用copymemory方式, 复制到结构中, 结果和直接传结构地址是一样的. 难得要逐个复制到结构的每个field里? 谢谢.
补充:VB , API