I've been doing some interesting work for Cincom that should be appearing in a future release of VisualWorks. I now have the ability to call VisualWorks as a DLL (on Windows) or a shared object library (on Linux or *nix). On Windows, for example, you can use ResHacker to add the image to the VisualWorks DLL and call it from a C application.
The following functions are supported (among others):
- stInitializeSupervisor - startup VisualWorks in a separate thread
- stEvaluate (char *expression) - evaluate the expression and return the result
- stSendMessage (stObject *receiver, char *selector, ...) send the message to the given receiver and return the result
- stReleaseSupervisor - shutdown VisualWorks if nobody else is using it
The objects returned to C are in a structure that gives C direct access to the data for primitive objects (integer, float, double, character, string, symbol, etc.) and references to objects in a registry in Smalltalk for non-primitive objects.
Here's an example of C code that calls VisualWorks:
#include <stdio.h>
#include <vwcallin.h>
int main(int argc, char *argv[])
{
stInitializeSupervisor();
stObject *object1 = stEvaluate("(3@4) + (5@7)");
stObject *object2 = stSendMessage (object1, "printString");
if (object2->type == StringType)
printf ("%s\n", object2->stringValue);
else
printf ("Operation failed\n");
stReleaseObjectHandle (object1);
stReleaseObjectHandle (object2);
stReleaseSupervisor();
printf ("Press ENTER to finish\n");
getchar();
return 0;
}
The nice thing about this is that the same interface can be used to call into VisualWorks from a separate thread using a shared memory interface or by a socket interface to VisualWorks running in a different process or even on a different computer. The shared memory interface uses a mechanism similar to Thapi - the Smalltalk image continues to run while one Smalltalk process waits on a semaphore for a request from C. When it gets one, it wakes up, processes the request, and waits for another.
The socket interface is a bit slower but allows you to talk to a Smalltalk image running in another process or on another system. It would be quite easy to establish a Smalltalk-Smalltalk link using this mechanism as well to allow your image to talk to another image. I know this is already provided by OpenTalk, but OpenTalk can't be called from a C program as well.
Pretty cool stuff.