PhotonDemon wrote:Hi Marten,
I'm sorry to bother you once again. The OleWrapped object you help with above has a method called #getData that should return the resultant PDF file as a string or at least a means of getting to the string data or byte array. It, #getData returns an #OSVariantarg, I expect this is an OS pointer of some type but I can't quite seem to figure out how to get to the string data. If you could find the time to give me one more example, I would greatly appreciate it.
Thanks, Lou
I installed the stuff again and yes: the object returned is actually of type OSVariantarg. The subtype within this OSVariantarg is (Array | UI8) ( -> vt = 8209 -> 8192 | 17), which is an array of unsigned byte-wide numbers - or in a Smalltalk world: a ByteArray.
Now - how to get the content of the ByteArray:
1) From the OLE object you should retrieve the OLE object to hold an array (instance of OSSafearray):
anInstance getData parray
2) now ask the Safearray for its content:
anInstance getData parray asMSKByteArray
To get this work add the following two methods to OSSafearray:
- Code: Select all
numberOfElements
"^<Integer | AbtError> This method returns the number of elements in the structure. If an error occurs
this method return an instance of AbtError
"
| numberOfElements numberOfDimensions lowerBound upperBound errorFlag |
numberOfElements := 0.
errorFlag := false.
lowerBound := OSInt32 calloc.
upperBound := OSInt32 calloc.
1 to: self safeArrayGetDim do: [ :eachDimensionIndex |
errorFlag := errorFlag | ((self safeArrayGetLBound: eachDimensionIndex asParameter plLbound: lowerBound asParameter) ~= SOk).
errorFlag := errorFlag | ((self safeArrayGetUBound: eachDimensionIndex asParameter plUbound: upperBound asParameter) ~= SOk).
errorFlag ifFalse:[ numberOfElements := numberOfElements + ((upperBound at: 0) - (lowerBound at:0) ) + 1 ]
].
lowerBound free.
upperBound free.
^errorFlag ifTrue:[ AbtError errorText: 'Error while retrieving number of elements in savearray' ] ifFalse:[ numberOfElements ].
- Code: Select all
asMSKByteArray
"^ <ByteArray> | <AbtError> Returns a byte array. The receiver is assumed to be a 1-dimensional array of
unsigned byte values: VtUI8
"
| temp byteArray safeArrayCopy arrayAddress numberOfElements |
(numberOfElements := self numberOfElements) isAbtError ifTrue:[ ^numberOfElements ].
" Create a copy of the OSSafearray using the API in the OSSafearray instance. 'temp' will contain it"
temp := ByteArray new: 4.
self safeArrayCopy: temp.
" Create a new instance of OSSafearray based on the address of the copy from the previous steps "
safeArrayCopy := self class address: (temp uint32At: 0 ).
" Get the data area (array contents) out of the safe array using the API in OSSafearray instance "
temp := ByteArray new: 4.
safeArrayCopy safeArrayAccessData: temp.
" Statement below gets the address of the data array. For strings, this is an array of addresses "
arrayAddress := temp uint32At: 0.
"for UI8 this seems to be a pointer to the memory, where the content is ..."
byteArray := (OSPtr address: arrayAddress) memcpyFrom: 0 to: (numberOfElements - 1).
" this seems to be needed ??
safeArrayCopy safeArrayUnaccessData
"
^byteArray
Especially in the last method I'm not sure, if there is a memory leak: safeArrayCopy - but that would need additional Google searches to find out ...
After all you will get a ByteArray with the PDF content ...
Just a warning: I'm not an expert in the OLE stuff and perhaps it can be done much more elegant or better or perhaps even correct (:-)) ... I just want to show a way how it could be done ....
Marten