From askoh.net wiki
Squeak4.0
Squeak4.0 DLL
- Open Squeak4.0.sln
- Right-clicked Squeak4.0, choose Add -> New Item.... Choose Visual C++ -> code -> C++ File(.cpp), and fill name with dll.c.
#include <stdio.h>
#include <string.h>
#include "dll.h"
EXPORT int SqueakInterp(int rcvr, char* selector, int arg) {
atom = 0;
return interpret(rcvr, selector, arg, "");
}
EXPORT int SqueakInterp1(int rcvr, char* selector, char* arg){
atom = 1;
return interpret(rcvr, selector, -1, arg);
}
EXPORT int SqueakGetFloat(int floatOop, double* floatValue){
dllFloatValueOf(floatOop, floatValue);
}
EXPORT void SqueakInit(void) {
squeakMain();
}
- Right-clicked Squeak4.0, choose Add -> New Item.... Choose Visual C++ -> code -> Header File(.h), and fill name with dll.h.
#ifdef BUILD_DLL
/* DLL export */
#define EXPORT __declspec(dllexport)
#else
/* EXE import */
#define EXPORT __declspec(dllimport)
#endif
int atom;
EXPORT int SqueakInterp(int rcvr, char* selector, int arg);
EXPORT int SqueakInterp1(int rcvr, char* selector, char* arg);
EXPORT int SqueakGetFloat(int floatOop, double floatValue);
EXPORT void SqueakInit(void);
- Under Configuration Properties -> General -> Configuration Type, set Dynamic Library(.dll).
- Under C/C++ -> Preprocessor -> Preprocessor Definition, fill in BUILD_DLL;WIN32;_DEBUG;_WINDOWS;__i386__;_CRT_SECURE_NO_DEPRECATE;VM_NAME=\"Squeak\";_USE_32BIT_TIME_T;VM_VERSION=\"SqueakDLL\".
- interp.c line 715, add these lines
static sqInt* dllMemory[20];
sqInt memCount = 0;
sqInt dllRcvr;
char* dllSelector;
char *dllArgString;
sqInt dllArg;
sqInt interpReturn;
- interp.c line 4920, add these lines
int dllFloatValueOf(sqInt floatOop, double* floatValue){
*floatValue = floatValueOf(dllMemory[floatOop]);
}
- interp.c line 6450-6461, replace these lines with
sqInt interpret(int rcvr, char* selector, int arg, char* argString) {
sqInt localReturnValue;
sqInt localReturnContext;
sqInt localHomeContext;
char* localSP;
char* localIP;
sqInt currentBytecode;
dllRcvr = rcvr;
dllSelector = selector;
dllArgString = argString;
dllArg = arg;
interpReturn = 0;
- interp.c line 8557, add these lines
if(interpReturn)
return memCount++;
- interp.c line 21931, add these lines
sqInt primitiveCString(void) {
sqInt sz;
sqInt s;
//printTop();
sz = cStringlength();
s = instantiateClassindexableSize(splObj(ClassString), sz);
getCStringLength(s + BaseHeaderSize, sz);
popthenPush(1, s);
}
sqInt primitiveReturnString(void){
static sqInt temp;
if ( interpReturn == 0) {
interpReturn = 1;
temp = nilObject();
}
temp = dllMemory[memCount]= popStack();
if(!isIntegerObject(temp))
addGCRoot(&dllMemory[memCount]);
}
sqInt primitiveRcvrArg(void){
sqInt rcvrOrArg;
usqInt oop;
rcvrOrArg = integerValueOf(popStack());
if(rcvrOrArg && (dllArg != -1))
popthenPush(1, dllMemory[dllArg]);
else if ((rcvrOrArg == 0) && (dllRcvr != -1))
popthenPush(1, dllMemory[dllRcvr]);
else
popthenPush(1, nilObj);
}
- sqWin32Window.c line 2518, add these lines
int cStringlength(void)
{
return lstrlen(dllSelector);
}
int getCStringLength(int cStringIndex, int length)
{
char *cString= (char *)cStringIndex;
int count, i;
char anyString [100];
strcpy(anyString, dllSelector);
count = lstrlen(anyString);
for (i= 0; i < count; i++)
cString[i]= (char) anyString[i]; /* will remove leading zeros from unicode */
return count;
}
- sq.h line 446, add these lines
extern char *dllSelector;
extern char *dllArgString;
- sqWin32Intel.c line 1194, edit
int squeakMain (HINSTANCE hInst,
- sqWin32Intel.c line 1211, edit
GetModuleFileNameW(null, vmNameW, MAX_PATH);
- sqWin32Intel.c line 1179, comment the line
// interpret();
MainProgram
- Create a new empty project named MainProgram. Fill in Location: as "MyRoot\VS2008\Projects". Under Solution:, choose add to solution.
- Right-clicked MainProgram, choose Add -> New Item.... Choose Visual C++ -> code -> C++ File(.cpp), and fill name with main.c.
#include <windows.h>
#include <stdio.h>
#define sqPtr int
struct point{
sqPtr sPoint;
double x;
double y;
};
struct line {
sqPtr sline;
struct point start;
struct point end;
double length;
};
char sqExpression[50]= "";
double getFloat(sqPtr floatOop);
void setPoint(struct line *aLine, struct point *aPoint, double x, double y);
void lineNew(struct line *aLine);
void pointNew(struct point *aPoint, int x, int y);
void printPoint(struct point *aPoint);
void printVelocity(struct line *aLine);
void setStartPoint(struct line *aLine, double x, double y);
void setEndPoint(struct line *aLine, double x, double y);
void setVelocity(struct line *aLine, double x, double y);
void getStartPoint(struct line *aLine);
void getEndPoint(struct line *aLine);
int main () {
typedef void (*pfunc)();
struct line cline1;
/*Windows handle*/
HANDLE hdll;
/*A pointer to a function*/
pfunc SqueakInit;
pfunc SqueakInterp1;
pfunc SqueakInterp2;
/*LoadLibrary*/
hdll = LoadLibrary("Squeak4.0.dll");
/*GetProcAddress*/
SqueakInit = (pfunc)GetProcAddress(hdll, "SqueakInit");
SqueakInterp1 = (pfunc)GetProcAddress(hdll, "SqueakInterp1");
SqueakInterp2 = (pfunc)GetProcAddress(hdll, "SqueakInterp2");
SqueakInit();
//create a line
lineNew(&cline1);
printPoint(&cline1.start); //0@0
printPoint(&cline1.end); //3@3
printVelocity(&cline1); //1@1
//set start point
setStartPoint(&cline1, 1.1, 3.3);
printPoint(&cline1.start); //1.1@3.3
printPoint(&cline1.end); //3@3
printVelocity(&cline1); //1@1
//set velocity
setVelocity(&cline1, 0.01, 0.03);
printVelocity(&cline1); //0.01@0.03
//move 1.1s
perform4(cline1.sline, "moveTime:", "1.1");
printPoint(&cline1.start); //1.1@3.3
printPoint(&cline1.end); //3@3
printVelocity(&cline1); //1@1
getStartPoint(&cline1);
getEndPoint(&cline1);
printPoint(&cline1.start); //1.111@3.311
printPoint(&cline1.end); //3.011@3.011
return 0;
}
sqPtr perform1(char* selector){
return SqueakInterp( -1, selector, -1);;
}
sqPtr perform2(sqPtr rcvr, char* selector){
return SqueakInterp(rcvr, selector, -1);
}
sqPtr perform3(sqPtr rcvr, char* selector, sqPtr args){
return SqueakInterp(rcvr, selector, args);
}
sqPtr perform4(sqPtr rcvr, char* selector, char* args){
return SqueakInterp1(rcvr, selector, args);
}
void printPoint(struct point *aPoint){
printf("\nPoint: %f @ %f", aPoint->x, aPoint->y);
}
void getStartPoint(struct line *aLine){
float x, y;
sqPtr aPoint;
aPoint = perform2(aLine->sline, "startPoint");
aLine->start.x = getFloat(perform2(aPoint, "x"));
aLine->start.y = getFloat(perform2(aPoint, "y"));
}
void getEndPoint(struct line *aLine){
float x, y;
sqPtr aPoint;
aPoint = perform2(aLine->sline, "endPoint");
aLine->end.x = getFloat(perform2(aPoint, "x"));
aLine->end.y = getFloat(perform2(aPoint, "y"));
}
void printVelocity(struct line *aLine){
float x, y;
sqPtr velocity;
velocity = perform2(aLine->sline, "velocity");
x = getFloat(perform2(velocity, "x"));
y = getFloat(perform2(velocity, "y"));
printf("\nVelocity: %f @ %f", x, y);
}
void setStartPoint(struct line *aLine, double x, double y){
//exe side point
aLine->start.x = x;
aLine->start.y = y;
//dll side point
sprintf(sqExpression, "%f@%f", x, y );
aLine->start.sPoint = perform1(&sqExpression);
perform3(aLine->sline, "startPoint:", aLine->start.sPoint);
}
void setEndPoint(struct line *aLine, double x, double y){
//exe side point
aLine->end.x = x;
aLine->end.y = y;
//dll side point
sprintf(sqExpression, "%f@%f", x, y );
aLine->end.sPoint = perform1(&sqExpression);
perform3(aLine->sline, "endPoint:", aLine->end.sPoint);
}
//set velocity at smalltalk side only.
void setVelocity(struct line *aLine, double x, double y){
//velocity only stored at dll side
sprintf(sqExpression, "%f@%f", x, y );
perform3(aLine->sline, "velocity:", perform1(&sqExpression));
}
double getFloat(sqPtr floatOop){
double temp;
SqueakGetFloat(floatOop, &temp);
return temp;
}
void lineNew(struct line *aLine){
aLine->sline = perform1("SqLine new");
setStartPoint(aLine, 0, 0);
setEndPoint(aLine, 3, 3);
setVelocity(aLine, 1, 1);
aLine->length = perform2(aLine->sline, "length");
}
- Right-click on MainProgram, choose Set as StartUp Project.
- Right-click on MainProgram, choose Project Dependencies..., check Squeak4.0.
Debug
- Copy Squeak4.1.changes, Squeak4.1.image and SqueakV41.sources into MyRoot/Debug.
- Click Debug, choose the correct image file.
- In Squeak window, open a workspace, execute this once "SqueakDLL initialise" and then execute/debug "SqueakDLL processDLL" for every exe call to dll.