< Day Day Up > |
The C-level extensibility mechanism lets you implement Flash extensibility files using a combination of JavaScript and C code. The process for implementing this capability is summarized in the following steps:
For more information, see "Sample DLL implementation" on page 540. C-level extensibility and the JavaScript interpreterThe C code in the DLL or shared library interacts with the Flash JavaScript API at three different times:
To accomplish these tasks, the interpreter defines several data types and exposes an API. Definitions for the data types and functions that are listed in this section appear in the mm_jsapi.h file. For your library to work properly, you must include the mm_jsapi.h file at the top of each file in your library, with the following line: #include "mm_jsapi.h" Including the mm_jsapi.h file includes the mm_jsapi_environment.h file, which defines the MM_Environment structure. To get a copy of the mm_jsapi.h file, extract it from the sample ZIP or SIT file (see "Sample DLL implementation" on page 540), or copy the following code into a file that you name mm_jsapi.h: #ifndef _MM_JSAPI_H_ #define _MM_JSAPI_H_ / ************************************************************************ ***** * Public data types ************************************************************************ ****/ typedef struct JSContext JSContext; typedef struct JSObject JSObject; typedef long jsval; #ifndef JSBool typedef long JSBool; #endif typedef JSBool (*JSNative)(JSContext *cx, JSObject *obj, unsigned int argc, jsval *argv, jsval *rval); /* Possible values for JSBool */ #define JS_TRUE 1 #define JS_FALSE 0 / ************************************************************************ ***** * Public functions ************************************************************************ ****/ /* JSBool JS_DefineFunction(unsigned short *name, JSNative call, unsigned int nargs) */ #define JS_DefineFunction(n, c, a) \ (mmEnv.defineFunction ? (*(mmEnv.defineFunction))(mmEnv.libObj, n, c, a) \ : JS_FALSE) /* unsigned short *JS_ValueToString(JSContext *cx, jsval v, unsigned int *pLength) */ #define JS_ValueToString(c, v, l) \ (mmEnv.valueToString ? (*(mmEnv.valueToString))(c, v, l) : (unsigned short *)0) /* unsigned char *JS_ValueToBytes(JSContext *cx, jsval v, unsigned int *pLength) */ #define JS_ValueToBytes(c, v, l) \ (mmEnv.valueToBytes ? (*(mmEnv.valueToBytes))(c, v, l) : (unsigned char *)0) /* JSBool JS_ValueToInteger(JSContext *cx, jsval v, long *lp); */ #define JS_ValueToInteger(c, v, l) \ (mmEnv.valueToInteger ? (*(mmEnv.valueToInteger))(c, v, l) : JS_FALSE) /* JSBool JS_ValueToDouble(JSContext *cx, jsval v, double *dp); */ #define JS_ValueToDouble(c, v, d) \ (mmEnv.valueToDouble ? (*(mmEnv.valueToDouble))(c, v, d) : JS_FALSE) /* JSBool JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp); */ #define JS_ValueToBoolean(c, v, b) \ (mmEnv.valueToBoolean ? (*(mmEnv.valueToBoolean))(c, v, b) : JS_FALSE) /* JSBool JS_ValueToObject(JSContext *cx, jsval v, JSObject **op); */ #define JS_ValueToObject(c, v, o) \ (mmEnv.valueToObject ? (*(mmEnv.valueToObject))(c, v, o) : JS_FALSE) /* JSBool JS_StringToValue(JSContext *cx, unsigned short *bytes, uint sz, jsval *vp); */ #define JS_StringToValue(c, b, s, v) \ (mmEnv.stringToValue ? (*(mmEnv.stringToValue))(c, b, s, v) : JS_FALSE) /* JSBool JS_BytesToValue(JSContext *cx, unsigned char *bytes, uint sz, jsval *vp); */ #define JS_BytesToValue(c, b, s, v) \ (mmEnv.bytesToValue ? (*(mmEnv.bytesToValue))(c, b, s, v) : JS_FALSE) /* JSBool JS_DoubleToValue(JSContext *cx, double dv, jsval *vp); */ #define JS_DoubleToValue(c, d, v) \ (mmEnv.doubleToValue ? (*(mmEnv.doubleToValue))(c, d, v) : JS_FALSE) /* jsval JS_IntegerToValue(long lv); */ #define JS_IntegerToValue(lv) (((jsval)(lv) << 1) | 0x1) /* jsval JS_BooleanToValue(JSBool bv); */ #define JS_BooleanToValue(bv) (((jsval)(bv) << 3) | 0x6) /* jsval JS_ObjectToValue(JSObject *obj); */ #define JS_ObjectToValue(ov) ((jsval)(ov)) /* unsigned short *JS_ObjectType(JSObject *obj); */ #define JS_ObjectType(o) \ (mmEnv.objectType ? (*(mmEnv.objectType))(o) : (unsigned short *)0) /* JSObject *JS_NewArrayObject(JSContext *cx, unsigned int length, jsval *v) */ #define JS_NewArrayObject(c, l, v) \ (mmEnv.newArrayObject ? (*(mmEnv.newArrayObject))(c, l, v) : (JSObject *)0) /* long JS_GetArrayLength(JSContext *cx, JSObject *obj) */ #define JS_GetArrayLength(c, o) \ (mmEnv.getArrayLength ? (*(mmEnv.getArrayLength))(c, o) : -1) /* JSBool JS_GetElement(JSContext *cx, JSObject *obj, jsint idx, jsval *vp) */ #define JS_GetElement(c, o, i, v) \ (mmEnv.getElement ? (*(mmEnv.getElement))(c, o, i, v) : JS_FALSE) /* JSBool JS_SetElement(JSContext *cx, JSObject *obj, jsint idx, jsval *vp) */ #define JS_SetElement(c, o, i, v) \ (mmEnv.setElement ? (*(mmEnv.setElement))(c, o, i, v) : JS_FALSE) /* JSBool JS_ExecuteScript(JSContext *cx, JSObject *obj, unsigned short *script, * unsigned int sz, jsval *rval) */ #define JS_ExecuteScript(c, o, s, z, r) \ (mmEnv.executeScript ? (*(mmEnv.executeScript))(c, o, s, z, _T(__FILE__), \ __LINE__, r) : JS_FALSE) /* JSBool JS_ReportError(JSContext *cx, unsigned short *error, unsigned int sz) */ #define JS_ReportError(c, e, s) \ (mmEnv.reportError ? (*(mmEnv.reportError))(c, e, s) : JS_FALSE) / ************************************************************************ ***** * Private data types, macros, and globals ************************************************************************ ****/ typedef struct { JSObject *libObj; JSBool (*defineFunction)(JSObject *libObj, unsigned short *name, JSNative call, unsigned int nargs); unsigned short *(*valueToString)(JSContext *cx, jsval v, unsigned int *pLength); unsigned char *(*valueToBytes)(JSContext *cx, jsval v, unsigned int *pLength); JSBool (*valueToInteger)(JSContext *cx, jsval v, long *lp); JSBool (*valueToDouble)(JSContext *cx, jsval v, double *dp); JSBool (*valueToBoolean)(JSContext *cx, jsval v, JSBool *bp); JSBool (*valueToObject)(JSContext *cx, jsval v, JSObject **op); JSBool (*stringToValue)(JSContext *cx, unsigned short *b, unsigned int sz, jsval *vp); JSBool (*bytesToValue)(JSContext *cx, unsigned char *b, unsigned int sz, jsval *vp); JSBool (*doubleToValue)(JSContext *cx, double dv, jsval *vp); unsigned short *(*objectType)(JSObject *obj); JSObject *(*newArrayObject)(JSContext *cx, unsigned int length, jsval *vp); long (*getArrayLength)(JSContext *cx, JSObject *obj); JSBool (*getElement)(JSContext *cx, JSObject *obj, unsigned int idx, jsval *vp); JSBool (*setElement)(JSContext *cx, JSObject *obj, unsigned int idx, jsval *vp); JSBool (*executeScript)(JSContext *cx, JSObject *obj, unsigned short *script, unsigned int sz, unsigned short *file, unsigned int lineNum, jsval *rval); JSBool (*reportError)(JSContext *cx, unsigned short *error, unsigned int sz); } MM_Environment; extern MM_Environment mmEnv; // Declare the external entry point and linkage. #ifdef _WIN32 # ifndef _MAC // Windows __declspec( dllexport ) void MM_InitWrapper( MM_Environment *env, unsigned int envSize ); # else // Mac with MSVC++ Win32 portability lib extern void MM_InitWrapper( MM_Environment *env, unsigned int envSize ); # endif #else // Codewarrior # pragma export on extern void MM_InitWrapper( MM_Environment *env, unsigned int envSize ); # pragma export off #endif #define MM_STATE \ /* Definitions of global variables */ \ MM_Environment mmEnv; \ \ void \ MM_InitWrapper(MM_Environment *env, unsigned int envSize) \ { \ extern void MM_Init(); \ \ char **envPtr = (char **)env; \ char **mmPtr = (char **)(&mmEnv); \ char **envEnd = (char **)((char *)envPtr + envSize); \ char **mmEnd = (char **)((char *)mmPtr + sizeof(MM_Environment)); \ \ /* Copy fields from env to mmEnv, one pointer at a time */ \ while (mmPtr < mmEnd && envPtr < envEnd) \ *mmPtr++ = *envPtr++; \ \ /* If env doesn't define all of mmEnv's fields, set extras to NULL */ \ while (mmPtr < mmEnd) \ *mmPtr++ = (char *)0; \ \ /* Call user's MM_Init function */ \ MM_Init(); \ } \ #endif /* _MM_JSAPI_H_ */ Sample DLL implementationA sample DLL implementation is located in ZIP and SIT files in the ExtendingFlash/dllSampleComputeSum folder (see "Sample implementations" on page 19). To see how the process works without actually building the DLL, you can do the following:
This section discusses the development of the sample. In this case, the DLL contains only one function, which adds two numbers. The C code is shown in the following example: // Source code in C // Save the DLL or shared library with the name "Sample". #include <windows.h> #include <stdlib.h> #include "mm_jsapi.h" // A sample function // Every implementation of a JavaScript function must have this signature. JSBool computeSum(JSContext *cx, JSObject *obj, unsigned int argc, jsval *argv, jsval *rval) { long a, b, sum; // Make sure the right number of arguments were passed in. if (argc != 2) return JS_FALSE; // Convert the two arguments from jsvals to longs. if (JS_ValueToInteger(cx, argv[0], &a) == JS_FALSE || JS_ValueToInteger(cx, argv[1], &b) == JS_FALSE) return JS_FALSE; /* Perform the actual work. */ sum = a + b; /* Package the return value as a jsval. */ *rval = JS_IntegerToValue(sum); /* Indicate success. */ return JS_TRUE; } After writing this code, build the DLL file or shared library, and store it in the appropriate External Libraries directory (see "Integrating C functions" on page 534). Then create a JSFL file with the following code, and store it in the Commands directory (see "Saving JSFL files" on page 7). // JSFL file to run C function defined above. var a = 5; var b = 10; var sum = Sample.computeSum(a, b); fl.trace("The sum of " + a + " and " + b + " is " + sum ); To run the function defined in the DLL, select Commands > Sample in the Flash authoring environment. |
< Day Day Up > |