请问怎么把个TMemoryStream和VARIANT 相互转换????听说这个问题难倒众多高手,他们只会用Delphi的代码来敷衍我??(100分)

  • 主题发起人 主题发起人 葬月
  • 开始时间 开始时间

葬月

Unregistered / Unconfirmed
GUEST, unregistred user!
我都急死了......谁告诉我
注意是VARIANT 不是Variant 也不是TVariant
 
Use VARIANTARG to describe arguments passed within DISPPARAMS. Use VARIANT to specify variant data that can't be passed by reference;
the VARIANT type can't have the VT_BYREF bit set. Note that VARIANTs can be passed by value even if VARIANTARGs cannot.
typedef struct FARSTRUCT tagVARIANT VARIANT;
typedef struct FARSTRUCT tagVARIANT VARIANTARG;

typedef struct tagVARIANT {
VARTYPE vt;
unsigned short wReserved1;
unsigned short wReserved2;
unsigned short wReserved3;
union {
unsigned char bVal; /* VT_UI1 */
short iVal; /* VT_I2 */
long lVal; /* VT_I4 */
float fltVal; /* VT_R4 */
double dblVal; /* VT_R8 */
VARIANT_BOOL bool; /* VT_BOOL */
SCODE scode; /* VT_ERROR */
CY cyVal; /* VT_CY */
DATE date; /* VT_DATE */
BSTR bstrVal; /* VT_BSTR */
Iunknown FAR* punkVal; /* VT_UNKNOWN */
Idispatch FAR* pdispVal; /* VT_DISPATCH */
SAFEARRAY FAR* parray; /* VT_ARRAY|* */
unsigned char FAR *pbVal; /* VT_BYREF|VT_UI1 */
short FAR* piVal; /* VT_BYREF|VT_I2 */
long FAR* plVal; /* VT_BYREF|VT_I4 */
float FAR* pfltVal; /* VT_BYREF|VT_R4 */
double FAR* pdblVal; /* VT_BYREF|VT_R8 */
VARIANT_BOOL FAR* pbool; /* VT_BYREF|VT_BOOL */
SCODE FAR* pscode; /* VT_BYREF|VT_ERROR */
CY FAR* pcyVal; /* VT_BYREF|VT_CY */
DATE FAR* pdate; /* VT_BYREF|VT_DATE */
BSTR FAR* pbstrVal; /* VT_BYREF|VT_BSTR */
IUnknown FAR* FAR* ppunkVal; /* VT_BYREF|VT_UNKNOWN */
IDispatch FAR* FAR* ppdispVal; /* VT_BYREF|VT_DISPATCH */
SAFEARRAY FAR* FAR* parray; /* VT_ARRAY|* */
VARIANT FAR* pvarVal; /* VT_BYREF|VT_VARIANT */
void FAR* byref; /* Generic ByRef */
};
};

To simplify extracting values from VARIANTARGs, OLE Automation provides a set of functions for manipulating this type. Use of these functions is strongly recommended to ensure that applications apply consistent coercion rules. The functions are described in Chapter 6, "Data Manipulation Functions."
The vt value governs the interpretation of the union as follows:
Value Description
VT_EMPTY No value was specified. If an argument is left blank, you should not return VT_EMPTY for the argument. Instead, you should return the VT_ERROR value: DISP_E_MEMBERNOTFOUND.
VT_EMPTY | VT_BYREF Illegal.
VT_UI1 An unsigned 1-byte character is stored in bVal.
VT_UI1 | VT_BYREF A reference to an unsigned 1-byte character was passed;
a pointer to the value is in pbVal.
VT_I2 A 2-byte integer value is stored in iVal.
VT_I2 | VT_BYREF A reference to a 2-byte integer was passed;
a pointer to the value is in piVal.
VT_I4 A 4-byte integer value is stored in lVal.
VT_I4 | VT_BYREF A reference to a 4-byte integer was passed;
a pointer to the value is in plVal.
VT_R4 An IEEE 4-byte real value is stored in fltVal.
VT_R4 | VT_BYREF A reference to an IEEE 4-byte real was passed;
a pointer to the value is in pfltVal.
VT_R8 An 8-byte IEEE real value is stored in dblVal.
VT_R8 | VT_BYREF A reference to an 8-byte IEEE real was passed;
a pointer to its value is in pdblVal.
VT_CY A currency value was specified. A currency number is stored as an 8-byte, two's complement integer, scaled by 10,000 to give a fixed-point number with 15 digits to the left of the decimal point and 4 digits to the right. The value is in cyVal.
VT_CY | VT_BYREF A reference to a currency value was passed;
a pointer to the value is in pcyVal.
VT_BSTR A string was passed;
it is stored in bstrVal. This pointer must be obtained and freed via the BSTR functions, which are described in Chapter 6, "Data Manipulation Functions."
VT_BSTR | VT_BYREF A reference to a string was passed. A BSTR* which points to a BSTR is in pbstrVal. The referenced pointer must be obtained or freed via the BSTR functions.
VT_NULL A propagating NULL value was specified. This should not be confused with the NULL pointer. The NULL value is used for tri-state logic as with SQL.
VT_NULL | VT_BYREF Illegal.
VT_ERROR An SCODE was specified. The type of the error is specified in scode. Generally, operations on error values should raise an exception or propagate the error to the return value, as appropriate.
VT_ERROR | VT_BYREF A reference to an SCODE was passed. A pointer to the value is in pscode.
VT_BOOL A Boolean (True/False) value was specified. A value of 0xFFFF (all bits one) indicates True;
a value of 0 (all bits zero) indicates False. No other values are legal.
VT_BOOL | VT_BYREF A reference to a Boolean value. A pointer to the Boolean value is in pbool.
VT_DATE A value denoting a date and time was specified. Dates are represented asdo
uble-precision numbers, where midnight, January 1, 1900 is 2.0, January 2, 1900 is 3.0, and so on. The value is passed in date.This is the same numbering system used by most spreadsheet programs, although some incorrectly believe that February 29, 1900 existed, and thus set January 1, 1900 to 1.0. The date can be converted to and from an MS-DOS representation using VariantTimeToDosDateTime, discussed in Chapter 6, "Data Manipulation Functions."
VT_DATE | VT_BYREF A reference to a date was passed. A pointer to the value is in pdate.
VT_DISPATCH A pointer to an object was specified. The pointer is in pdispVal. This object is only known to implement IDispatch;
the object can be queried as to whether it supports any other desired interface by calling QueryInterface on the object. Objects thatdo
not implement IDispatch should be passed using VT_UNKNOWN.
VT_DISPATCH | VT_BYREF A pointer to a pointer to an object was specified. The pointer to the object is stored in the location referred to by ppdispVal.
VT_VARIANT Illegal. VARIANTARGs must be passed by reference.
VT_VARIANT | VT_BYREF A pointer to another VARIANTARG is passed in pvarVal. This referenced VARIANTARG will never have the VT_BYREF bit set in vt, so only one level of indirection can ever be present. This value can be used to support languages that allow functions to change the types of variables passed by reference.
VT_UNKNOWN A pointer to an object that implements the IUnknown interface is passed in punkVal.
VT_UNKNOWN | VT_BYREF A pointer to a pointer to the IUnknown interface is passed in ppunkVal. The pointer to the interface is stored in the location referred to by ppunkVal.
VT_ARRAY | <anything> An array of data type <anything> was passed. (VT_EMPTY and VT_NULL are illegal types to combine with VT_ARRAY). The pointer in pByrefVal points to an array descriptor, which describes the dimensions, size, and in-memory location of the array. The array descriptor is never accessed directly, but instead is read and modified using the functions described in Chapter 6, "Data Manipulation Functions."
上面是关于VARIANT的帮助说明,按我的理解,好像是不行的吧!
能不能考虑其他方法解决?可以说说你的问题本身吗?
 
很简单呀
VARIANT类型和Delphi的TVarData完全一致, 而VarArray类型就是VARIANT中的SAFEARRAY呀
所以: 要把TMemoryStream转成VARIANT可以用下面代码:
var
v: Variant;
m: TMemoryStream;
p: PChar;
begin
.....
v := VarArrayCreate([0, m.Size-1], vtByte);
p := VarArrayLock(v);
m.ReadBuffer(p^, m.size);
VarArrayUnLock(v);
// 这里的v已经是VARIANT类型了
end;

end;
 
那是Delphi
在C++Builder 里VarArrayCreate怎么用??
我只想把个文件流通过调用服务端方法来传递到服务端
服务端那个方法是个VARIANT的参数
 
这问题你问了很多次了……我也没往深处想,为什么参数一定要是VARIANT的呢?通常I/O
读写函数的参数都是无类型指针,你为什么不也定为无类型指针呢?
 
我想通过COM上传个文件到另外一个电脑里去???
我不知道用void *是否可以 我印象中void * char * 只是个指针, 只是个地址位置
我不知道能否传送
所以我想用VARIANT保险点
 
VARIANT是16个字节,转换一下不太难把
 
不太难,,那么麻烦你帮我转换一下
 
在一般的I/O函数中,参数使用无类型指针是为性能考虑的,它发送的实际上是指针指向的
数据,而不是指针本身。试想如果不使用指针的话,每一份需要读写(收发)的数据都要
被复制一份,如果对象很大的话,这样在空间和效率上就都不理想了。
你的程序还是那个用COM来实现的吗?
 
是啊 我一定要用COM来实现,而且一定学会用VARIANT来传递 如果真的不行,那我只能放弃
Borland的东西了
 
bcb中不会没有varArrayCreate吧?
你不会查查unit system中的源代码吗?
 
我看不懂源代码,,,也看不懂英语
你看的懂吗?看的懂的话告诉我,我把分给你
 
不用看懂呀。
你直接在资源管理器里搜索上面提到的几个函数找到定义它们的cpp文件不就知道调用格式
了吗?
 
我很笨的,,你能否举个例子??
 
to 葬月:
>>那是Delphi
>>在C++Builder 里VarArrayCreate怎么用??
在C++Builder中,VarArrayCreate的用法大致是这样的,下面是它的函数原型:
extern PACKAGE Variant __fastcall VarArrayCreate(const int * Bounds, const int Bounds_Size, int VarType);
其中,参数的含义:
(1)Bounds 意为“边界”
声明的形式一般是这样的:int Bounds[n] = {x1, x2, y1, y2......};
就是说这其中的每一对数值(x1,x2算是第一对,y1,y2算是第二对......)是最终的可变
类型数组中某一维的上下边界(上下边界:就是某一维数组的第一个和最后一个元素的下
标序号)。
比如:int Bounds[4] = {0, 1, 0, 2};
这说明要定义一个2x3的二维可变类型数组,第一维有2个元素,其中第一个元素和最后
一个元素的下标是0和1;第二维有3个元素,其中第一个元素和最后一个元素的下标
就是0和2
所以,我们能看出来,Bounds数组中的元素的个数必须是偶数。
(2)Bounds_size是Bounds数组(再说一遍,这里说的是Bounds数组,不是最终你定义的可变类型数组)
中最后一个元素的下标序号,所以,一定是个奇数
比如:上面那个int Bounds[4] = {0, 1, 0, 2};
在Bounds数组中有4个元素,最后一个元素是Bounds[3],所以,Bounds_size是3
(3)VarType一般设为varVariant就行。
用法举例:
这个例子是在大富翁离线数据库中查找满足下面两个条件的记录
条件一:姓名是“葬月”,条件二:时间是“2002-5-29 12:00:00”
[法一]
TLocateOptions SearchOptions;
//这是Locate用到的一个集合类型
int Bounds[2] = {0, 1};
//说明最终的可变类型数组是一个有2个元素的一维数组
Variant MyArray;
MyArray = VarArrayCreate(Bounds, 1, varVariant);
MyArray.PutElement("葬月", 0);
//下面两句是给这个数组的两个元素赋值
MyArray.PutElement(StrToDateTime(String("2002-5-29 12:00:00")), 1);
bool SearchResult;
SearchResult = Table1->Locate("UserFrom;DateTime", MyArray, SearchOptions);
//上面的两个条件分别对应"UserFrom;DateTime"这两个字段
if(SearchResult)
Caption = "找到了!";
else
Caption = "没找到";
[法二]
VarArrayCreate明显是在C++Builder中使用Delphi的东西。所以,下面的用法也是正确的,与上面效果一样:
TLocateOptions SearchOptions;
Variant MyArray[2];
//这里的声明和赋值就象是普通的数组一样,没用到VarArrayCreate
MyArray[0] = "葬月";
MyArray[1] = Variant(StrToDateTime(String("2002-5-29 12:00:00")));
bool SearchResult;
SearchResult = Table1->Locate("UserFrom;DateTime", VarArrayOf(MyArray,1), SearchOptions);
if(SearchResult) //这里和上面的方法稍有不同
Caption = "找到了!";
else
Caption = "没找到";
怎么样?解释得够详细的吧 :-) 多给我点分吧,哈哈 :p

BTW:>>我很笨的,,你能否举个例子??
以后,不要轻易说出这样没有自信的话!
 
我真的很笨,看了你的例子还是不知道怎么把void * 转换为 VARIANT
你知道的话就告诉我吧,,,要么就是你也不知道
 
请你给出你的代码
 
其实原理相当简单:
就是将你特定数据结构中的所有数据复制到一个variant变量“指向”的内存中。
说“指向”其实没错。 variant实际可以认为是一个可变类型的指针与可以直接存放少量定长数据的结合物, 只不过它指向的内存是你程序无法直接访问的。
VarArrayCreate是定义并分配一个variant, 它内部存放的是一个array, array中元素的类型由vararraycreate时指定, 指定varByte是说明array中每个元素存放的数据是字节(目前计算机可以储存数据的最小单位, 任何其他类型都可以表示成一个或多个字节)。
VarArrayLock其实就是锁定variant array具体存放数据的那块内存以使你的程序可以直接对它进行读写。
VarArrayUnLock就不必说了。
我们既然用vararraylock取得了variant array指向那块内存的首地址, 当然可以将我们希望的任何数据写入。
那么我么可以将Stream中包含的所有数据复制进去。 这样也就达到了你将TStream转换成Variant的目的了。
 
TMemoryStream *Stream=new TMemoryStream();
Stream->LoadFromFile("D://ime.exe");
Stream->Seek(0,0);
void* P;
int Bounds[2] = {0, Stream->Size - 1};
Variant V = VarArrayCreate(Bounds, sizeof(Bounds), varByte);
P = VarArrayLock(V);
Stream->Position = 0;
Stream->Read(P, Stream->Size);
VarArrayUnlock(V);
运行到VarArrayCreate说 Error Createing Variant Array
 
???老大,我在上面辛辛苦苦地写了那么一大段话,看来你根本就没认真地看啊!!!还口口声声地
说自己笨!!!唉......
>>Variant V = VarArrayCreate(Bounds, sizeof(Bounds), varByte);
这一句错得多明显啊!应该是这样:
Variant V = VarArrayCreate(Bounds, 1, varByte);
 
后退
顶部