Delphi程序使用VC做的服务器组件数据发生的奇怪问题!请高手帮忙,分不够可以再给!!!

zhangjl716 2003-09-12 12:13:56
我用VC做了一个简单的EXE形式的服务器组件,组件接口提供方法为
GetData([in,out]MYSTRUCT *pMyDataIn_Out);

数据结构类型为:
typedef struct tagMYSTRUCT{
unsigned char v1;
float v2;
double v3;
}MYSTRUCT


我在服务器组件中只修改了结构pMyDataIn_Out数据成员的值。


问题:(1)当用Delphi程序做客户程序,调用该组件的方法,返回的参数不正确。比如本来我需要返回的v3= 1.1,但程序可能读出的数据为-12344E-304这样的数据。
(2)我原来做过这样的程序,在WIN2000平台上,使用Delphi6和VC6,开发的程序没有问题。而我现在的平台是WINXP,请高手指点是否因为平台和开发环境的问题?怎么解决??

另外:如果我的输入输出数据结构定义成:
typedef struct tagMYSTRUCT{
unsigned char v1;
unsigned char v2;
unsigned char v3;
}MYSTRUCT

typedef struct tagMYSTRUCT{
double v1;
double v2;
double v3;
}MYSTRUCT时(即结构里的数据元素同种类型),程序调用返回的结果都没问题!!!!


那为兄弟请帮忙解决一下,将不胜感激!!!

...全文
80 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhangjl716 2003-09-15
  • 打赏
  • 举报
回复
问题已经解决,特别谢谢masterz和akun!
xiaohedou 2003-09-14
  • 打赏
  • 举报
回复
Look ^ study
zhangjl716 2003-09-13
  • 打赏
  • 举报
回复
谢谢akun,问题还没最终解决:

昨天在我的IDL文件前加了#pragma pack(1),可以把in属性的参数问题解决了,但out属性的参数返回的值还是不对(同样必须要求结构内数据元素类型相同才行)


masterz兄弟,因为今天比较忙,大概看了一下你的解释,还没来得及按照说的做,非常感谢你的指导。
masterz 2003-09-13
  • 打赏
  • 举报
回复
//////////////////////////////////////////////////////////
HOWTO: Use structs in Automation-compatible interfaces

Structs, also known as User Defined Types (UDTs), can be used in Automation- compatible interfaces since Win NT4 SP4 and DCOM 1.2 for Win9x. An Automation- compatible struct may contain only primitive Automation types as its members. Nesting structs is not allowed, but VARIANT is allowed thus enabling nested structs (you can store a struct in a VARIANT). In order for a struct to be usable for Automation-compatible interfaces, the struct must be described in a type library and it must be declared with its own GUID:


[uuid(21602F40-CC62-11d4-AA2B-00A0CC39CFE0)]
struct MyStruct
{
[helpstring("A long value")]
long nLongValue;

[helpstring("A string")]
BSTR bstrStringValue;
};

// Later in the IDL file
[uuid(...), version(...), helpstring(...)]
library MyLib
{
...
struct MyStruct;
};

For unknown reason, the MIDL compiler bundled with VC6 has not been updated even in SP4. Therefore, you need the latest Platform SDK installed on your computer (or at least no older than Platform SDK Jul'99) in order to compile the above IDL code and any IDL using structs with Automation.

NOTE: The current release of MIDL at the time of writing (5.03.0280) does not support the helpstring() attribute on the struct itself. helpstring() is supported on the struct fields, though.

Once your struct is declared as above, you can pass it via Automation- compatible interfaces. Keep in mind, however, that only struct pointers can be passed:


HRESULT SendStruct([in] struct MyStruct *pData);
HRESULT GetStruct([out, retval] struct MyStruct *pData);

Structs can also be passed in safe arrays and VARIANTs:


HRESULT SendManyStructs([in] SAFEARRAY(struct MyStruct) *psaData);

Neither IDL nor Automation define byte alignment for a struct. VB assumes 4-byte alignment, while #import in VC assumes 8-byte alignment. For most Automation structs this isn't an issue. However, if you use 8-byte types like double, this may make a difference:


[uuid(...), helpstring(...)]
struct BadAlign
{
long nLongValue;
double dblDoubleValue;
};

For VB, the double field starts at the fourth byte of the struct, while for VC's #import it starts at the eight byte. This poses a significant problem. It can be solved by adding an inject_statement clause to #import:


#import "My.tlb" inject_statement("#pragma pack(4)")

IMPORTANT: Structs cannot be used by scripting clients!

Implementing structs in code is usually trivial - just use the struct directly. There are two specific struct uses when the code is fairly non-trivial - when using a safe array of structs and when stuffing the struct into a VARIANT. Let's note first that in Automation any struct is represented via an IRecordInfo interface pointer. The object exposing this interface is implemented by the Automation runtime and is acquired via the following two API functions:


GetRecordinfoFromGuids
GetRecordInfoFromTypeInfo

When structs are used in say dual interfaces, this detail is hidden from the implementer and the user of the interface. Only the marshaler knows and uses it. However, when we need to pass structs in a VARIANT or a safe array, we have to delve into these details ourselves. Here's the C++ code for populating a VARIANT with a struct (error checking omitted):


VARIANT vnt;
IRecordInfo *pRI;
MyStruct data;
HRESULT hr;

data.nLongValue = 5;
data.bstrStringValue = SysAllocString(L"Something");
hr = GetRecordInfoFromGuids(LIBID_MyLib, 1, 0, 0x409, uuidof(MyStruct), &pRI);
VariantInit(&vnt);
vnt.vt = VT_RECORD;
vnt.pvRecord = &data;
vnt.pRecInfo = pRI;
pRI = NULL;

Note that the VARIANT doesn't own the storage for the embedded struct, but VariantClear will free the content of the struct by calling IRecordInfo::RecordClear. Note also that the common VARIANT wrapper classes like CComVariant and _variant_t don't support structs. Finally, note that the mechanism for storing struct data in a VARIANT is not fully documented. For example it isn't clear how a struct can be returned in an [out] VARIANT argument without producing memory leaks.

Now let's see how to populate a safe array with structs. The following code is a trimmed down version of the MSDN example code (error checking omitted):


SAFEARRAY *psa;
SAFEARRAYBOUND sab = {2, 0};
MyStruct *pData;
IRecordInfo *pRI;
HRESULT hr;

hr = GetRecordInfoFromGuids(LIBID_MyLib, 1, 0, 0x409, uuidof(MyStruct), &pRI);
psa = SafeArrayCreateEx(VT_RECORD, 1, &sab, pRI);
pRI->Release();
pRI = NULL;
hr = SafeArrayAccessData(psa, (void**)&pData);
pData[0].nLongValue = 1;
pData[0].bstrStringValue = SysAllocString(L"First");
pData[1].nLongValue = 2;
pData[1].bstrStringValue = SysAllocString(L"Second");
hr = SafeArrayUnaccessData(psa);

Unlike a VARIANT, a safe array owns the storage of its structs.

The UDT documentation is located at: mk:@MSITStore:D:\MSDN\Automat.Chm::/htm/chap12_3rcj.htm (Copy the link and paste it in the "Jump to URL..." box. Substitute the path with the path to your MSDN files. This link is obtained from MSDN Library Oct'2000.)
masterz 2003-09-13
  • 打赏
  • 举报
回复
HOWTO: Use structs in COM interfaces when Automation compatibility is not an issue

You can use any IDL type for the struct fields. You don't need to associate a GUID with the struct. Structs can be nested. About the only issue is using data pointers within the structs. When a struct is marshaled, all embedded pointers have to be marshaled as well. This amounts to copying the target locations of those pointers in the marshaling packet. Therefore, all pointers must be annotated, especially if they point to arrays. If an embedded pointer is not annotated with one of the three pointer types (ref, unique, and ptr), the pointer_default() attribute of the interface the struct is used in determines the type of the pointer. Since different interfaces can potentially use different default embedded pointer types, it is generally a good idea to always annotate the struct's embedded pointers. Here's an example:


struct Data
{
DWORD nData1;
float fltData2;
};

struct MyStruct
{
int nCount;
[unique, size_is(nCount)] struct Data *aData;
};

When passing structs one should be careful what gets transmitted in the marshaling packet. In the above example the whole array of Data structs is transferred. This is expected and well annotated. However, there are bad struct designs as well. Consider the following single-linked list:


struct Node
{
struct Data data;
[unique] struct Node *pNext;
};

When the head of the list is passed, all elements in the list are replicated in the marshaling packet. Such architecture needs to be redesigned so the complete list does not get transferred on each method call (a possible design is to hide the list itself behind an object and expose methods on the object's interface for manipulating the list).

Rarely, but sometimes nevertheless, pointer aliasing has to be considered as well. In the examples so far no two pointers could point to the same memory address. However, consider this doubly- linked list:


struct Node
{
struct Data data;
[ptr] struct Node *pNext;
[ptr] struct Node *pNext;
};

True, this is a bad design, but nonetheless without the pointer type set to [ptr], the result would be disastrous.

When a struct is an [in] argument, it doesn't matter how the memory pointed to by the embedded pointers is allocated. However, for [out] and [in, out] arguments all memory pointed to by the embedded pointers of a struct must be allocated via the COM memory allocator (CoTaskMemAlloc). This is necessary so that the marshaling code can deallocate the data at the callee and reallocate it at the caller.

A final point: IDL doesn't define the struct packing byte alignment. The default for the VC compiler is 8. However, it is safer to manually inject a #pragma pack statement:


#pragma pack(push, 8)
...
#pragma pack(pop)

If you manually set the byte alignment, don't use #import for importing the struct definition from a type library. It adds #pragma pack(push, 8) at the beginning of the generated TLH file. Your pragma is not persisted in the generated type library. Generally, it is not advised to use #import for non-Automation-compatible interfaces.

IMPORTANT: since your interfaces are not Automation-compatible, you have to build and register the proxy/stub DLL for their marshaling support!


akun 2003-09-12
  • 打赏
  • 举报
回复
可能是数据对齐的问题
+上下面一句
#pragma pack(1)
Delphi 是Borland 公司推出的面向对象的可视化编程工具,它拥有功能强大的集成 开发环境(IDE)和世界上速度极快的编译器,并且兼具Visual C++的强大功能和Visual Basic 易学易用的特点。“真正的程序员用VC,聪明的程序员用Delphi”—这句话就 是对Delphi 最贴切的描述。 本书几乎囊括了Delphi 7 进行实用程序开发的全部知识,并结合大量实用而又有代 表性的开发示例进行讲解。使读者能够方便、顺利地掌握Delphi 的各项开发技术。 全书为22 章,各部既相互独立又相互联系,逐步引导读者深入学习并掌握 Delphi。 第1 章:介绍Delphi 的发展历史及特点,并讲述Delphi 的新功能及安装、卸载方法。 第2 章:详细介绍Delphi 的集成开发环境。 第3 章:详细介绍了Delphi 的应用程序框架,并简要介绍了如何使用Delphi 工程管理 器管理项目。 第4 章:介绍Object Pascal 的编程语法结构,只有熟练掌握这些知识,才可以编写 出高质量的Delphi 程序。 第5 章:主要介绍面对对象编程的基础知识,简单介绍了可视化类库VCL 的结构和 Delphi 程序的大致运行过程。 第6 章:主要介绍了VCL 简单组件的编程技巧与主要属性、方法、事件的使用方法。 第7 章:介绍操作相对复杂组件的编程技巧与主要属性、方法、事件的使用方法。 第8 章:主要讲解Delphi 窗体编程方法。 第9 章:详细讲解Delphi 的事件,并介绍主要事件的使用方法。 第10 章:主要讲解文件操作类命令与函数,并详细介绍如何使用Delphi 进行文件 操作。 第11 章:主要讲解如何使用Delphi 进行图像编程工作。 第12 章:主要讲解Delphi 多媒体编程技术,并结合大量示例向读者展示Delphi 强 大的多媒体开发技术支持。 第13 章:详细讲解Delphi 的消息处理机制,并列举大量示例介绍Delphi 消息处理 程序的编写方法。只有完全掌握这些知识,才可以从事Delphi 组件开发工作。 第14 章:介绍Delphi 多线程编程技术,掌握多线程编程技术对于开发大型程序, 及提高应用程序运行效率都有很大帮助。 第15 章:介绍如何使用动态链接库和组件,这也是使用Delphi 第三方控件扩展现有功 能的基础知识。 第16 章:大体讲解使用Delphi 开发VCL 组件的方法。 第17 章:主要讲解Delphi 数据库开发工具基础知识,只有熟练掌握这些工具的使 用方法,才可以以更高的效率开发数据库应用程序。 第18 章:主要讲解客户/服务器应用程序编程要领。 第19 章:大体讲解多层应用程序的开发要领。 第20 章:详细讲解Delphi 报表组件使用方法,除此之外,还简单讲解了Delphi 决策组 件的使用方法。 第21 章:主要讲解Delphi 开发数据程序的大体步骤,并以“图书管理系统”为 例,向读者介绍Delphi 开发实用程序的一般步骤。 ·2· 第22 章:主要介绍Delphi 的Internet 网络应用技术,并详细讲解开发过程中最常用的组 件—Indy 组件。 对于初学者,此书可以作为不可多得的Delphi 入门教程,对于有一定基础的中高级水平 的开发人员,本书也提供了关于Delphi 的新特点和使用方法,并提供了相应的实例,可以帮 助其快速提高开发水平。
使用糖果专业下载组件,可以使你的软件在网络数据获取方面达到专业水准,而无需了解复杂的网络底层和网络协议。 糖果专业下载组件在以下方面有突出优势: 1 极快的下载速度,在同等网络条件下(相同目标文件,相同客户机),糖果下载组件下载速度超出一些专业下载软件 (参考:迅雷的下载速度真的是迅雷不及掩耳吗?); 2 很低的CPU占用率,即使在5个线程,下载速度超过300k/s时, 糖果下载组件进程CPU使用率不到1%; 3 程序随时可以退出,永不"假死". 网络程序最忌讳让用户等待,而我们所见到的一些技术不过关的软件动不动就没反应了,让用户莫名其妙。糖果下载组件即使在域名解释不了或连接不上服务器时依然可以响应用户操作。 4 支持ISA代理服务器的Windows集成身份认证(NTLM认证)。ISA Server是大中型企业网络管理首选防火墙软件,采用 NTLM认证 可以与Windows桌面管理完美结合并增强网络安全。糖果下载组件 可以实现只要IE可以上网,就能下载数据,而无需用户任何额外设置。 5 多源多线程下载技术:多源多线程下载技术从客户端处解决了服务器和网络的资源问题,让客户端自主选择网络速度,服务器速度最快的地方获取数据。 这种方案比在服务器负载平衡有明显的优越性: 举例说明: 如果你的软件用户布在 网通,电信,教育网中,只需在三个网中各放置一台服务器,糖果下载组件下载数据时,同时指定3台服务器地址,就会从响应最快的服务器上获取数据使用糖果下载组件,可以让你的软件轻松达到或超越专业的网络软件的水准,让你的精力聚焦在业务上,无需在网络底层或操作系统层面上浪费更多时间。 糖果下载控件以ActiveX(ocx)方式提供编程接口,易于使用. 包含 一个多线程下载软件的VC演示工程,Delphi演示工程(含源码)和NTLM认证的VC演示工程,Delphi演示工程(含源码).
精通Delphi数据库设计与实例开发配套光盘很难找到的光盘。 图书简介: Delplli是Borland公司推出的可视化开发工具,它拥有世界上最快的编译器,并提供了丰富的组件集、强大的代码自动生成功能和丰富的数据库管理工具等,使用它的集成开发环境,编程人员可以更快地建立应用程序。"真正的程序员用C(语言),聪明的程序员用DeIphi(语言)--这句话是对Delphi最经典、最实在的描述。和VC相比,Delphi更简单、更易于掌握.在能上却丝毫不逊色:和VB相比,Del phi则功能更强大,更实用。可以说Delphi同时兼备了VC功能强大和VB简单易学的特点,因此成为了无数程序员挚爱的编程工具。 开发数据库应用系统是一项复杂的工程,而在众多的编程工具中,Delphi数据库方面的特长尤为突出:它适应于多种数据库结构,包括从客户/服务器模式到多层数据结构模式;具有高效率的数据库管理系统和新一代更先进的数据库引擎提供了最新的数据析手段大量的企业组件。因此,使用Delphi开发数据库系统可以大大减轻程序员的工作量,缩短系统的开发周期。 本书系统而全面地讲解了使用Delpt"1i开发数据库应用程序的方法,包括Delphi的快速入门、Object PascaI的语法基础、基本组件使用方法、数据库基础知识、数据库环境设置、连接数据库的方法、使用BDE和ADO等组件进行各种数据操作的方法、数据控制组件使用方法、报表和图表的设计方法、存储过程和触发器的使用方法、建立多层布式数据库应用程序的方法,以及设计Web数据程序的方法。值得一提的是,在第1 4章~第1 7章中详细展示了超市管理系统、贸易管理系统、影碟租赁系统和酒店管理系统4个数据库应用案例的开发过程。这些案例功能完整、界面简洁,并且具有很高的实用价值,稍加改动即可直接应用于实际的工作环境中。这些综合案例的讲解并非仅仅介绍相关程序构造、搭建过程,而是与前面的基础知识综合贯穿起来,将理论知识与实际操作完美结合,强化读者的学习效果。最后,本书还介绍了使用install shield发布数据库应用程序的方法。 本书循序渐进、由浅入深、系统全面地讲解了使用Delphi开发数据库应用程序的各种方法和技巧,在其中的关键知识点上均列举了针对性很强的小程序来进行讲解,方便读者进行学习。对于Delpl"1i的初级用户,通过本书的学习可以轻松理解Delphi数据库相关的基础知识,以及快速掌握使用Delphi开发数据库应用程序的方法;而对于Delphi的中级用户,本书那些较为详尽且具有较强实用性和针对性的开发数据库系统的关键技术和技巧,也能够为这一层次的读者提供解决实际问题的思路与方案。 同时,本书配套光盘中提供了书中全部应用实例的效果文件及源程序代码。相信通过对 操作步骤的详细讲解和典型案例的系统析,能够帮助读者融会贯通Delphi数据库开发的各种方法和技巧,从而开发出真正适合企业应用的数据库系统。 本书适合于Delphi的初中级读者,也可作为广大Delphi程序爱好者、相关从业技术人 或高等院校相关专业师生教学的参考用书。 由于本书作者水平有限,书中不足之处在所难免,敬广大读者批评指正。

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧