Objects as Binary Resources...

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Objects as Binary Resources...

Umur
Is there a way to stream in a smalltalk binary object emdedded in an exe
file instead of loading from a file?


Reply | Threaded
Open this post in threaded view
|

Re: Objects as Binary Resources...

Blair McGlashan
"umur" <[hidden email]> wrote in message
news:[hidden email]...
> Is there a way to stream in a smalltalk binary object emdedded in an exe
> file instead of loading from a file?

Yes. You can either stream it from a ByteArray held in the image (which is
effectively how view resources are normally saved and loaded), or you could
add an RT_RCDATA (i.e. binary blob) resource to your executable stub, and
then update this with the STB data you want to store there at deployment
time in a custom image stripper.

Loading STB from a byte array rather than a file is trivial, e.g.

    bytes := 'Hello' binaryStoreBytes.
    (Object fromBinaryStoreBytes: bytes)     "Ctrl+D/DisplayIt"

OR:

    (Object binaryReadFrom: bytes readStream)        "Ctrl+D/DisplayIt"

Various other levels of abstraction are possible, but essentially STB works
off a binary stream so it makes sense to pass streams around, and then you
can choose the source/destination for the streaming.

If you use a byte array in the image, you need take no further action at
deployment time, other than ensuring it is stored in a class or global that
will not get stripped.

In order to load STB from a real Win32 resource you will first need to get
it into the .exe file as such. This can be done by overriding the
ImageStripper>>updateStubResources: method. I've attached an example below.

Regards

Blair

--------------------------------------------------------------------------------------------
| package |
package := Package name: 'HelloWorldResource'.
package paxVersion: 0;
 basicComment: 'Dolphin Smalltalk Hello World from STB Resource
Copyright (c) Object Arts Ltd, 2004.

This package is intended to demonstrate loading an STB resource stored in a
deployed executable.'.

package imageStripperBytes: (ByteArray fromBase64String:
'IVNUQiAxIEYPDwAEAAAATXlJbWFnZVN0cmlwcGVyAAAAAAAAAABSAAAAEgAAAEhlbGxvV29ybGRS
ZXNvdXJjZVIAAAA6AAAAT2JqZWN0IEFydHNcU2FtcGxlc1xNVlBcSGVsbG8gV29ybGRcSGVsbG9X
b3JsZFJlc291cmNlLmV4ZZoAAAAAAAAAUgAAABIAAABIZWxsb1dvcmxkUmVzb3VyY2VSAAAAGgAA
AE15SGVsbG9Xb3JsZFNlc3Npb25NYW5hZ2Vy7/8lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAA=').

package classNames
 add: #MyHelloWorld;
 add: #MyHelloWorldSessionManager;
 add: #MyImageStripper;
 yourself.

package binaryGlobalNames: (Set new
 yourself).

package globalAliases: (Set new
 yourself).

package allResourceNames: (Set new
 yourself).

package setPrerequisites: (IdentitySet new
 add: '..\..\..\Dolphin\Base\Dolphin';
 add: 'Hello World';
 add: '..\..\..\Dolphin\Lagoon\Lagoon Image Stripper';
 yourself).

package!

"Class Definitions"!

ImageStripper subclass: #MyImageStripper
 instanceVariableNames: ''
 classVariableNames: ''
 poolDictionaries: ''
 classInstanceVariableNames: ''!
HelloWorldSessionManager subclass: #MyHelloWorldSessionManager
 instanceVariableNames: ''
 classVariableNames: ''
 poolDictionaries: ''
 classInstanceVariableNames: ''!
HelloWorld subclass: #MyHelloWorld
 instanceVariableNames: ''
 classVariableNames: ''
 poolDictionaries: ''
 classInstanceVariableNames: ''!

"Global Aliases"!


"Loose Methods"!

"End of package definition"!

"Source Globals"!

"Classes"!

MyImageStripper guid: (GUID fromString:
'{8BC9839E-6E29-4A00-A6FF-8C20BA3D5736}')!
MyImageStripper comment: ''!
!MyImageStripper categoriesForClass!MVP-Models! !
!MyImageStripper methodsFor!

updateStubResources: anExternalHandle
 | data |
 super updateStubResources: anExternalHandle.
 data := 'Hello STB Resource World' binaryStoreBytes.
 (KernelLibrary default
  updateResource: anExternalHandle
  lpType: 10   "RT_RCDATA"
  lpName: 999  "Unique id for the resource"
  wLanguage: 0
  lpData: data
  cbData: data size) ifFalse: [KernelLibrary default systemError] ! !
!MyImageStripper categoriesFor: #updateStubResources:!operations!private! !

MyHelloWorldSessionManager guid: (GUID fromString:
'{6146C1BC-729B-45F3-8C06-09DF25D7297D}')!
MyHelloWorldSessionManager comment: ''!
!MyHelloWorldSessionManager categoriesForClass!Samples! !
!MyHelloWorldSessionManager class methodsFor!

mainShellClass
 "Answer the class of the application's main window (a <Shell> presenter)."

 ^MyHelloWorld! !
!MyHelloWorldSessionManager class categoriesFor:
#mainShellClass!constants!public! !

MyHelloWorld guid: (GUID fromString:
'{FC889F02-1FEC-4353-9E2B-0A9D252D3DE1}')!
MyHelloWorld comment: ''!
!MyHelloWorld categoriesForClass!MVP-Views! !
!MyHelloWorld methodsFor!

helloText
 ^(self loadSTBResource: 999
  fromLibrary: SessionManager current defaultResourceLibrary) ifNil: ['Hello
World']!

loadRawDataResource: anIntegerOrString fromLibrary:
anExternalResourceLibrary
 | address size bytes hFind kernel hRes hModule |
 kernel := KernelLibrary default.
 hModule := anExternalResourceLibrary asParameter.
 (hFind := kernel
    findResource: hModule
    lpName: anIntegerOrString
    lpType: 10 "RT_RCDATA") isNull
  ifTrue: [^nil].
 (hRes := kernel loadResource: hModule hResInfo: hFind) isNull ifTrue:
[^nil].
 (address := (kernel lockResource: hRes) asExternalAddress) isNull ifTrue:
[^nil].
 size := kernel sizeOfResource: hModule hResInfo: hFind.
 bytes := address copyFrom: 1 to: size.
 ^bytes!

loadSTBResource: anIntegerOrString fromLibrary: anExternalResourceLibrary
 ^(self loadRawDataResource: anIntegerOrString fromLibrary:
anExternalResourceLibrary)
  ifNotNil: [:bytes | Object fromBinaryStoreBytes: bytes]!

onPaintRequired: aPaintEvent
 | canvas rect |
 canvas := aPaintEvent canvas.
 rect := self clientRectangle.
 canvas text: self helloText at: rect center - (60 @ 10)! !
!MyHelloWorld categoriesFor: #helloText!public! !
!MyHelloWorld categoriesFor: #loadRawDataResource:fromLibrary:!private! !
!MyHelloWorld categoriesFor: #loadSTBResource:fromLibrary:!private! !
!MyHelloWorld categoriesFor: #onPaintRequired:!event handling!public! !

"Binary Globals"!

"Resources"!


Reply | Threaded
Open this post in threaded view
|

Re: Objects as Binary Resources...

Schwab,Wilhelm K
Blair,

> In order to load STB from a real Win32 resource you will first need to get
> it into the .exe file as such. This can be done by overriding the
> ImageStripper>>updateStubResources: method. I've attached an example below.

Is this something that should be obtained from the session manager
subclass?  It is rare to subclass ImageStripper; it is very common to
subclass session managers.

Have a good one,

Bill


--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Objects as Binary Resources...

Blair McGlashan
"Bill Schwab" <[hidden email]> wrote in message
news:cbq8gr$f3q$[hidden email]...

> Blair,
>
>> In order to load STB from a real Win32 resource you will first need to
>> get it into the .exe file as such. This can be done by overriding the
>> ImageStripper>>updateStubResources: method. I've attached an example
>> below.
>
> Is this something that should be obtained from the session manager
> subclass?  It is rare to subclass ImageStripper; it is very common to
> subclass session managers.

Well firstly this is a "rare" requirement - I think it is reasonable to
classify it as rare since I don't recall seeing such a request before. I
don't know the reason behind the request or which of the interpretations I
placed on it in my posting was correct, and I don't know why one would
choose to store STB as a Windows resource rather than a ByteArray in the
deployed image. Its possible a lot of people have wanted to do this, but no
one has asked before. If the request had arisen before, then its possible
there might be an easier way to perform this task that did not involve code,
but as it stands this can only be done in 5.1 by subclassing the
ImageStripper, and so I provided a simple sample to demonstrate how this
could be done. Secondly building the deployed executable is the task of the
"ImageStripper" (a historical name that only partly describes the function
of the object). The SessionManager's job is to manage the runtime
environment, not really to define what is in it. The ImageStripper does the
static stuff, the SessionManager the dynamic stuff, at least that's how I
see it anyway.

Regards

Blair