SkillAgentSearch skills...

Jsbindings

[DEPRECATED] JavaScript bindings for Objective-C and C

Install / Use

/learn @zynga/Jsbindings
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Please note: This project is deprecated at Zynga and is no longer maintained.


JavaScript Bindings for C and Objective-C

Introduction

JavaScript Bindings for C / Objective-C (JSB) is the "glue" code (or wrapper code) that sits between native code (C or Objective-C) and JavaScript (JS) code. JSB allows calling native code from JS and vice-versa.

That means that you can interact with your favorite native library from JS. As an example, you could create a cocos2d particle system in JS, while its logic and rendering will be executed natively. Or you could create a Chipmunk Physics world in JS, while the whole physics simulation, including the collisions detections, would run natively.

JSB layer

The JS code is interpreted by SpiderMonkey, Mozilla's JS virtual machine (VM). It uses the latest stable version of SpiderMonkey (as of this writing it is v19.0). The JS VM is extended by JSB to support custom types, custom structures and Objective-C objects.

JSB has a flexible set of rules that could be used to select the classes, methods, functions and structs to parse or ignore; which methods are callbacks; and renaming rules among some of its features. To ease the creation of these rules, it supports regular expressions.

Major features

Highlights of JSB:

  • Supports any Objective-C / C library
  • Automatically generates the JS bindings ("glue" code)
  • No need to modify the source code of your libraries, or the autogenerated code
  • Powerful set of rules and plugins to customize the generated JS API
  • Automatically converts JS objects/types into Objective-C objects/structs/ types and vice-versa
  • Supports "subclassing" native objects in JS
  • Supports callbacks
  • Automatically generates object oriented JS API from C libraries (provided that the C API is OO, like Chipmunk)

Creating your own bindings

Quick steps: Bindings Generation

  1. Download JSB

     $ git clone git://github.com/zynga/jsbindings.git
    
  2. Generate the BridgeSupport files for your project. Let's assume that your project is CocosDenshion

     $ cd ~/src/CocosDenshion/CocosDenshion
     $ gen_bridge_metadata -F complete --no-64-bit -c '-DNDEBUG -I.' *.h -o ~/some/path/CocosDenshion.bridgesupport
    
  3. Generate complement files for your project

     $ cd ~/src/CocosDenshion/CocosDenshion
     $ ~/jsb/generate_complement.py -o ~/some/path/CocosDenshion-complement.txt *.h
    
  4. Create a JSB config file for your project

     $ vim ~/some/path/CocosDenshion_jsb.ini
    
  5. Run the JSB generator script

     $ ~/jsb/generate_jsb.py -c ~/som/path/CocosDenshion_jsb.ini
    
  6. Include the recently autogenerated files and JSB source files in your Xcode project

  7. Include SpiderMonkey and JRSwizzle in your Xcode project

The CocosDenshion config files could be found here: configs/CocosDenshion

Quick steps: Adding the bindings to your project

  1. Include all the autogenerated files to your Xcode project. eg:

    src/auto/js_bidnings_PROJECTNAME_classes.*, src/auto/jsb_PROJECTNAME_functions.*, src/auto/jsb_PROJECTNAME_auto_classes.*,

  2. Include the following manual files to your Xcode project.

    src/manual/jsb_config.h, src/manual/jsb_core.*, src/manual/basic_conversions.*.

  3. For objective-c projects (not required for C-only projects like Chipmunk), you should include the following files:

    src/manual/js_bindigns_NS_manual.*

  4. Add a registration file. Name it: src/manual/jsb_PROJECTNAME_registration.mm. See src/manual/jsb_chipmunk_registration.mm as an example.

  5. Edit src/manual/jsb_core.mm and add a call your registration code. eg:

     // JSBCore class
     -(id) init
     {
     	// ...
     	JSB_register_PROJECTNAME(_cx, _object);
     	// ...
     }
    
  6. If you need to create manual JS bindings for your project, put those files int the src/manual directory. Name them:

    /src/manual/js_bidnings_PROJECTNAME_manual.*

  7. If you need to further extend your code from JS, create a JavaScript file (eg: see src/js/jsb_constants_chipmunk.js), and place it in the src/js directory.

  8. Add a #define to include your new bindings in src/manual/jsb_config.h. eg:

#ifndef JSB_INCLUDE_PROJECTNAME
#define JSB_INCLUDE_PROJECTNAME 1
#endif // JSB_INCLUDE_PROJECTNAME

Steps in detail

JSB comes with a python script called generate_jsb.py that generates the glue code. It needs a configuration file that contains the parsing rules and the BridgeSupport files.

BridgeSupport files are generated by a script called gen_bridge_metadata that is part of OS X, and generates xml files with information like class names, method names, arguments, return values, internals of the structs, constants, etc.

gen_bridge_metadata, internally, uses clang to parse the native code. The output is very reliable, but unfortunately, it is not complete: class hierarchy, protocols and properties data are missing. That's why JSB comes with another python script, called generate_js_complement.py, that generates the missing information.

Once we have the configuration file setup, we can run the generate_jsb.py script to generate the glue code.

To summarize, the structure of a JSB configuration file is:

  • Parsing rules (optional): renaming rules, classes to ignore / parse, etc...
  • BridgeSupport files (required): Class, methods, functions, structs information
  • Complement files (required for Objective-C projects): Hierarchy, protocol and properties information

"glue" code generation

The configuration file

The configuration has a set of powerful rules that could transform the native API into a customized JS API. Let's take a look at some of them.

Renaming rule

The renaming rule allows us to rename a method names or class names or function names or struct names. As an example, the default JS API for:

// CCAnimation (from cocos2d-iphone v2.0)
+(id) animationWithAnimationFrames:(NSArray*)arrayOfAnimationFrames delayPerUnit:(float)delayPerUnit loops:(NSUInteger)loops;

would be:

// ugly
cc.CCAnimation.animationWithAnimationFrames_delayPerUnit_loops_( frames, delay, loops );

So, with a simple set of rules, we can rename that JS API into this one:

// more JS friendly
cc.Animation.create( frames, delay, loops );

In order to do that, we need to remove the CC prefix from the class name, since it is already using the cc JS namespace:

obj_class_prefix_to_remove = CC

And finally we add a rename rule for that method:

method_properties = CCAnimation # animationWithAnimationFrames:delayPerUnit:loops: = name:"create",

Merge rule

But what happens with the other constructors of CCAnimation ?

// CCAnimation supports 4 different constructors
+(id) animation; //
+(id) animationWithSpriteFrames:(NSArray*)arrayOfSpriteFrameNames;
+(id) animationWithSpriteFrames:(NSArray*)arrayOfSpriteFrameNames delay:(float)delay;
+(id) animationWithAnimationFrames:(NSArray*)arrayOfAnimationFrames delayPerUnit:(float)delayPerUnit loops:(NSUInteger)loops;

What we should do, is to create a rule that merges the 4 constructors into one. JSB will call the correct one depending on the number of arguments. This is how the rule should look:

method_properties =  CCAnimation # animationWithAnimationFrames:delayPerUnit:loops: =  name:"create"; merge: "animation" | "animationWithSpriteFrames:" | "animationWithSpriteFrames:delay:",

And the code in JS will look like:

// calls [CCAnimation animation]
var anim = cc.Animation.create(); 

// calls [CCAnimation animnationWithSpriteFrames:]
var anim = cc.Animation.create(array);

// calls [CCAnimation animnationWithSpriteFrames:delay:]
var anim = cc.Animation.create(array, delay);

// calls [CCAnimation animationWithAnimationFrames:delayPerUnit:loops:]
var anim = cc.Animation.create(array, delay, loops);

Callback rule

JSB supports callback methods. In order to register a method as callback you should add a callback rule in the configuration file. eg:

method_properties = CCNode#onEnter = callback,

You could also rename a callback by doing:

method_properties = CCLayer # ccTouchesBegan:withEvent: = callback; name:"onTouchesBegan",

Configuration examples

In order to learn more about the configuration file, use the following working examples as a guideline:

Internals of the JS bindings ("glue" code)

The JS bindings code allows to call JS code from native and vice-versa. It forwards native callbacks to JS, and JS calls to native. Let's see them in detail:

Calling native functions from JS

The following code will call the the native C function ccpAdd():

var p1 = cc.p(0,0);
var p2 = cc.p(1,1);
// cc.pAdd is a "wrapped" function, and it will call the cocos2d ccpAdd() C function
var ret = cc.pAdd(p1, p2); 

Let's take a look at

Related Skills

View on GitHub
GitHub Stars389
CategoryDevelopment
Updated3mo ago
Forks64

Languages

Objective-C++

Security Score

77/100

Audited on Dec 18, 2025

No findings