Squeak
  links to this page:    
View this PageEdit this PageUploads to this PageHistory of this PageTop of the SwikiRecent ChangesSearch the SwikiHelp Guide
How to create plugins
Last updated at 5:18 pm UTC on 12 May 2017
 Smalltalk listLoadedModules

2008

Question Juergen Bullinger February 19, 2004: I am thinking about implementing an Interface to GMP (Linux), could you give me some advice about where to search for documentation on how to do that?
Answer Goran Krampe Here is a short summary with some good keywords for you to search on:
To interface with external libraries you either use FFI or build a plugin. For this I am pretty sure you want a plugin since the overhead for each call in FFI is high and I assume you want to be able to call "often".

A plugin is built something like this:
1. Write the BlablaPlugin class (check for samples in Squeak, base your code on the ones that subclass from SmartSyntaxInterpreterPlugin). This class represents the plugin and the methods in it is written in "Slang" - a subset of Smalltalk that is auto-translatable to C.
2. Learn how to use VMMaker. [also VMMakerTool]VMMaker produces the C-source for the VM and for all the plugins. Bring it up and let it generate your source onto disk into the source tree of the Squeak VM (that you have obtained elsewhere). You can get VMMaker to only regenerate the plugin. You also select using dragndrop to either generate an internal or external plugin. External is nice when developing since it can be loaded/unloaded, see below.
3. Build the VM using the tools for your OS, (make). If you had VMMaker to generate your plugin as an external it should have produced some C-code in a suitable place in the src-tree and make should have built a shared library for it.
4. From Squeak - write a method that references the primitive and try to call it. If all goes well it will autoload the plugin and run the primitive. You can see your loaded plugins using:
	SmalltalkImage current listLoadedModules 
A print it gives:
#('B2DPlugin 8 April 2003 (i)' 'SocketPlugin 8 April 2003 (i)'
'LargeIntegers v1.2 8 April 2003 (i)' 'BitBltPlugin 8 April 2003 (i)'
'SecurityPlugin 8 April 2003 (i)' 'FilePlugin 8 April 2003 (i)'
'MiscPrimitivePlugin 8 April 2003 (i)')
...and unload one using say:
 	SmalltalkImage current unloadModule: 'GtkPlugin'
It will be loaded again on demand.
Here is a silly example of a plugin primitive, itwill simply answer the size of a String sent in as an argument:
  GtkPlugin>>primitiveTest: aString
	| sz |
	self primitive: 'primitiveTest' parameters: #(String).
	sz _ interpreterProxy slotSizeOf: (aString asOop: String).
	^sz asOop: SmallInteger
...the above method will be auto-translated into C by VMMaker. Now in another class we can call it like this:
SomeClass>>test: aString
	<primitive: 'primitiveTest' module: 'GtkPlugin'>
	^self primitiveFailed

Question What is the VMMaker? I searched in my Squeak Image, but couldn't find it. There seems to be no Class with that name.
And also couldn't find a SmartSyntaxInterpreterPlugin-Class. Do I have to install it somehow first?
What about Slang? Can I generate binary executable code from within Squeak and call it afterwards somehow without having to rebuild the whole VM?
Answer How to save a parts bin:

Question Feb 18, 2004, How to create plugins wrote: I suspect that an external plugin is what I really want. [Refering to: FFI Caveats] I need to call out from Squeak to an external library of functions written in C, and I need to share data with these functions. The calls will all be synchronous, so I don't need to worry about callbacks. Is an external plugin, accessed by 'named primitive', the best way to do do this?
Answer tim Rowledge: You certainly should consider a plugin, but it can be internal or external at your option. [aFormObject asMorph, RBProgramNodeVisitor example] The code is identical and only the linking in your makefile would change. My suggestion would be to build it as an external especially when developing since
a) You don't need to do anything at all to the VM
b) You can load a version you think is working, try it, unload it, recompile to fix the bug (you realize there will be bugs, right :-) and reload it all without leaving squeak.
You will need to load VMMaker and get used to the way plugins are written. I strongly suggest working with SmartSyntaxInterpreterPlugin as your parent class since it makes a bunch of stuff simpler. Examine some of the simpler classes (like FileCopyPlugin?) and start small.

Using Tim Rowledge is pretty simple; lots of people have been able to do stuff with it. Basically you will want to open it, make sure your paths are set right, drag your plugin from 'available' to 'external' and use menu to 'generate plugin'. Then do makefile magic as appropriate to your platform.

Question How to create plugins February 27, 2004 :
Many, many thanks to Tim, and to John McIntosh for all of your help. I am happy to say that I am now building primitives as fast as I can!

A couple of questions which I am struggling with:

1. When passing parameters to a primitive, are there restrictions on the order or type of parameters that can be passed? Whenever I had an Array or Oop as the final parameter, I got the 'primitive has failed' exception. Moving to other-than final parameter seemed to fix it. I didn't try with single Array or Oop parameter though.
2. I need to pass (in both directions) arrays of Floats to and from primitives. Using examples from existing plugins, I am writing for example:
primitiveFoo: aFloatArray with: anIntegerBar
 	| arrayBase |
 	self var: #arrayBase declareC: 'double arrayBase'.
	self primitive: 'primitiveFoowith'
		parameters: #(Oop SmallInteger ).

	arrayBase _ self cCoerce: (interpreterProxy firstIndexableField: 
                  aFloatArray) to: 'double'.
	
	"then try to read/write to aFloatArray using:   "
		(arrayBase+arrayIndex)  _ 0.0 "for array accessing".
	"etc ... "
I try to invoke the primitive using something like:
setSomeArrayValues: aFloatArray andAnInt: anInt
 	
	^self primitiveFailed
There is definitely something wrong with the above for I cannot read correct values from the array within the primitive. What have I missed?

Answer Creating plugins for Squeak is not trivially easy. You typically need at least some knowledge of C as a base and then the best way to learn is to look at the other existing plugins.For developing plugins you first need to install VMMaker (from SqueakMap) and you need to have the tools needed to build a VM. So The first step is to make sure you can build a VM. If you are on Win32 those tools are neatly packaged on SF, if you are on Unix you typically find a lot of info at Ian's site: http://www-sor.inria.fr/~piumarta/squeak/devel.html The second step is to typically look at the Plugin classes, typically subclasses of SmartSyntaxInterpreterPlugin (which makes things easier than plain InterpreterPlugin) and make a trivial plugin.