User primitives are stored in shared libraries. A shared library called sample exists in the samples\primitiv directory. (For example, for OS/2 and Microsoft Windows, the primitiv subdirectory contains sample.dll.) The name of the sample library must be specified in the Smalltalk primitive declarations.
sample.c contains (at least) the following:
#include "esuser.h" #include <string.h> EsUserPrimitive(add2Numbers) { I_32 i1; I_32 i2; U_32 rc; EsObject retVal;
rc = EsIntegerToI32(EsPrimArgument(1), &i1); if (rc != EsPrimErrNoError) EsPrimFail(rc, 1); rc = EsIntegerToI32(EsPrimArgument(2), &i2); if (rc != EsPrimErrNoError) EsPrimFail(rc, 2); rc = EsI32ToInteger(i1 + i2, &retval); if (rc != EsPrimErrNoError) EsPrimFail(rc, EsPrimArgNumNoArg); EsPrimSucceed(retVal); }
EsObject sampleCStringToString(EsPrimVMContext, str) EsVMContext EsPrimVMContext; char * str; { EsObject result; U_32 i, size;
size = strlen(str); result = EsAllocateObject( EsPrimVMContext, EsPrimClassString, size, 0, (EsObject **) NULL);
if (result != (EsObject) NULL) for (i = 0; i < size; ++i) EsByteAtPut(result, i + 1, (U_8) str[i]); return result; }
EsUserPrimitive(exampleMakeAString) { EsObject result; result = sampleCStringToString(EsPrimVMContext, "This is a C string"); if (result == (EsObject) NULL) EsPrimFail(EsPrimErrNotEnoughMemory, EsPrimArgNumNoArg); EsPrimSucceed(result); }
#ifdef LINKED_USER_PRIMITIVES EsDefinePrimitiveTable(samplePrimitiveTable) EsPrimitiveTableEntry("add2Numbers", add2Numbers) EsPrimitiveTableEntry("exampleMakeAString", exampleMakeAString) EsEndPrimitiveTable #endif
In Smalltalk, add the following methods to UndefinedObject:
add: a and: b <primitive: 'sample':add2Numbers> ^self primitiveFailed makeAString <primitive: 'sample':exampleMakeAString> ^self primitiveFailed
Now evaluate the following in a workspace (the expected result follows the --->):
nil add: 54 and: 7 ---> 61 nil add: 16r7FFFFFFF and: 1 ---> -2147483648 (overflow) nil add: -1 and: -2 ---> -3 nil add: 1073741823 and: 1 ---> 1073741824 (LargeInteger) nil add: $a and: 2 ---> walkback "invalid class in argument 1" nil add: 0 and: 16r100000000 ---> walkback "value out of range in argument 2" nil makeAString ---> 'This is a C string'