VASmalltalk – Reconfiguration of PlatformFunctions

When accessing the ICU library one could consider to handle the problem of using different versions of ICU. The creators of ICU actually have a very “pessimistic” view of using a DLL: for each new version they create new names of functions and libraries.

As an example:

The versions of ICU are named “44”, “46”, “48”, “49” and “50”. Libraries are named according to this pattern: “icuuc49.dll” od “icuuc50.dll”.

The exported function names are working the same way: “ucal_add_49”, “ucal_add_50” …

The good thing here is, that the names are always identical in length and they have the same semantical meaning.

My first attempt to define the functions was following the classical VA way:

  "%%PRAGMA DECLARE
  (name: ICUFunctions isPool: true )
    (pool: ICUFunctions declarations: (
      (name: UCalAdd isConstant: true valueExpression: 'PlatformFunction fromArray: #(''C'' ''ucal_add_50'' nil ''icuin'' #(pointer int32 int32 pointer) #void)')
...

the normal way and the results are global constant – not changeable.

When playing around with reconfiguration of these definitions I changed the PRAGMA method to:

...
(pool: ICUFunctions declarations: (
  (name: UCalAdd isConstant: false valueExpression: 'PlatformFunction fromArray: #(''C'' ''ucal_add_50'' nil ''icuin'' #(pointer int32 int32 pointer) #void)')
...

but to my surprise nothing changed. I was not able to change the content of UCalAdd though I defined the variable as non constant. Reading the documentation shows the problem (as I interpet it this way). All pool variables filled with a valueExpression are defined as a non changeable constant and the values of this pool dictionary is inserted directly into the byte code of a compiled method.

Therefore the definitions of the pool variables and setting the values have to be two different things:

  "%%PRAGMA DECLARE
  (name: ICUFunctions isPool: true )
    (pool: ICUFunctions declarations: (
      (name: UCalAdd isConstant: false )
  ...

and

initializeUCalFunctions

"we do NOT define the platform function within the PRAGMA methods, because then they are not changeable any more"

UCalAdd :=
  PlatformFunction
    fromArray: #('C' 'ucal_add_49' nil 'icuin' (pointer int32 int32 pointer) void).
...

Now the methods (after recompiling) accesses the values of the pool variable in a dynamical way.

And now to the original question: how to reconfigure the platform functions. The only thing we have to do here now is:

* rename the function name (e.g. from uCal_Add_49 to uCal_Add_50)
* rename the library used for this function call

"Pretty ugly non public stuff

  VersionSuffic helds the new version "_50"
  CommonModule helds the new library name e.g. "icuin50.dll"

  ICUFunctions helds ALL function definitions
"
ICUFunctions keysAndValuesDo: [:key :eachPlatformFunction | 
 | functionName newFunctionName libraryIndex oldLibraryName newLibraryName |
 
 "we get the old function name"
 functionName := eachPlatformFunction name.
  "in ICU we have two $_ in the function name. the three 
   last characters have to be replaced  "
 newFunctionName := (functionName copyFrom: 1 to: functionName size - 3) , VersionSuffix.

 "get the old library name ..."
 oldLibraryName := eachPlatformFunction library physicalName asString.

 "and create the new library name with the additional 
  version information - based on the old library name
 "
 newLibraryName := (oldLibraryName indexOfSubCollection: (CommonModule copyFrom: 1 to: 4) ifAbsent: [0]) = 1
                     ifTrue: [CommonModule]
                     ifFalse: [I18NModule].

 "retrieve a possible new library index from VA"
 libraryIndex := PlatformLibrary libraryIndex: newLibraryName.

 "we set a new relation to a possible new library"
  eachPlatformFunction
    libraryIndex: libraryIndex;

  "and set address of the function to zero to force VA to 
  rebind it again before using it"
    unbind.

  "and change the function name"
  newFunctionName
    memcpyFrom: 0
    to: newFunctionName size - 1
    into: eachPlatformFunction
    startingAt: 12 + eachPlatformFunction parameterCount.

]
This entry was posted in Smalltalk and tagged , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s