Posts tagged "grammar checker"

Leveraging C/C++ libraries in the CS SDK using Alchemy

This post is going to walk through creating a CS Extension which checks grammar in InDesign. To achieve this, we’ll be using an Adobe Labs technology called Alchemy. If you’re not familiar, Alchemy is a tool that lets you compile C/C++ code into ActionScript bytecode. That means you can efficiently call into your C/C++ code from a pure ActionScript solution. This is especially exciting in the context of the Creative Suite because many developers already have a huge amount of existing code in C/C++. Here’s a brief demo:

 

 

Getting up and running with Alchemy

The following links should be enough to get you going:

Defining the interface

After Alchemy is set up, we next need to download an open-source C library called Link Grammar, you can get the source from here. While the library has plenty of features, we’ll just be using it to tell whether a sentence is grammatically correct or not. To call into this C library from ActionScript we need to define an interface that Alchemy can understand. We define this interface in the C code’s main function. Link Grammar defines a sample main in src/parse.c; replace it with this one, which defines the interface to Alchemy. Here are some magical lines to note:

AS3_Val setupFunction = AS3_Function( NULL, setup );
AS3_Val isThisGrammarFunction = AS3_Function( NULL, isThisGrammar );
AS3_Val result = AS3_Object( “setup: AS3ValType, isThisGrammar:AS3ValType”,

setupFunction, isThisGrammarFunction);

AS3_Release( setupFunction );
AS3_Release( isThisGrammarFunction );
AS3_LibInit( result );

 

This tells Alchemy that we have two C functions we want to expose to ActionScript; setup and isThisGrammar. Now all we have to do is flesh out these functions. For example, here’s our isThisGrammar function:

static AS3_Val isThisGrammar(void* self, AS3_Val args) {

Sentence sent;
int num_linkages;
char* val = NULL;
AS3_ArrayValue( args, “StrType”, &val );
sent = sentence_create(val, dict);
num_linkages = sentence_parse(sent, opts);
if (num_linkages > 0) {

sentence_delete(sent);
return AS3_True();

}
sentence_delete(sent);
return AS3_False();

}

 

This function first reads in a string passed from ActionScript and stores it in the variable val. We then pass val into the Link Grammar library. Based on the result, we return a Boolean to ActionScript telling it whether or not this sentence is grammatically correct. Notice, because we’re in C-land we have to keep in mind memory management (e.g. releasing the sentences when we’re done).

 

Compiling the library

Now that our interface is defined, let’s compile the C code into a swc. Since Alchemy uses a modified version of gcc, we pass it the compiler flag “-swc”. In the Link Grammar Makefile, we need only to change the rule which builds the binary so that it reads:

 

${BIN}/parse: ${OBJECTS}

${CC} ${CLDFLAGS} ${OBJECTS} -swc -o parse.swc

 

Running “make” from the command line will generate parse.swc. Easy as that!

 

From the ActionScript side

In most Alchemy use cases, all we have to do is initialize the C library and then call into the interfaces we defined:

var loader:CLibInit = new CLibInit();
var lib:Object = loader.init();
lib.setup();

 

However, it’s slightly more complex in our case. Alchemy requires that you pass any files needed by the C code as a byte array to the loader before calling your interfaces. Because the C code requires access to the file system (to read the dictionary, grammar rules, etc.), we’re going to need a function something like this:

private function supplyFile( loader:CLibInit, file:File, fileName:String):void {

var bytes:ByteArray = new ByteArray();
var stream:FileStream = new FileStream();
stream.open(file, FileMode.READ);
stream.readBytes(bytes, 0, stream.bytesAvailable);
stream.close();
loader.supplyFile(fileName, bytes);

}

 

And that’s all there is to it. To compile the CS Extension, generate the swc and copy it into the libs/ folder. At runtime, make sure you have the contents of Link Grammar’s data/ folder (which includes 4.0.dict, words/, etc.) copied onto the desktop.

 

 

Attached Files: