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'